打字稿转换 Object.entries 将派生字符串数组减少为文字类型
Posted
技术标签:
【中文标题】打字稿转换 Object.entries 将派生字符串数组减少为文字类型【英文标题】:typescript converting Object.entries reduced derived string array to literal types 【发布时间】:2022-01-03 16:54:46 【问题描述】:const program =
morgning: ['breakfast', 'mingle'],
evning: ['mingle', 'eat', 'party']
as const
const namespaceEvent = Object.entries(program).reduce(
(acc, [namespace, events]) => [...acc, ...events.map(event => `$namespace.$event`)],
[] as string[]
) // can't do 'as const' here;
type Namespace = typeof namespaceEvent[number] // sees the type as 'string' and not "morgning.breakfast" | "morgning.mingle" | "evning.mingle" | "evning.eat" | "evning.party"
const test: Namespace = 'foo.bar' // would like this to error
console.log(namespaceEvent) // ["morgning.breakfast", "morgning.mingle", "evning.mingle", "evning.eat", "evning.party"]
我该如何进行这项工作,为什么它不起作用?
【问题讨论】:
这能回答你的问题吗? Typescript Key-Value relation preserving Object.entries type 另外,这似乎很好地使用了flatMap
而不是reduce
。
@Aplet123 我非常愿意接受建议 - 你能分享一个代码示例吗?
【参考方案1】:
我认为这是解决这个问题的一种方法:
比我想象的要复杂得多,可能有更好的方法!
const program =
morgning: ['breakfast', 'mingle'],
evning: ['mingle', 'eat', 'party']
as const
type KV = [K in keyof typeof program]: `$K.$typeof program[K][number]`;
type NS = KV[keyof KV];
// type NS = "morgning.breakfast" | "morgning.mingle" | "evning.mingle" | "evning.eat" | "evning.party"
const namespaceEvent = Object.entries(program).reduce(
(acc, [namespace, events]) => [...acc, ...events.map(event => `$namespace.$event`)] as NS[],
[] as NS[]
)
const test: NS = 'foo.bar' // ERROR: Type '"foo.bar"' is not assignable to type 'NS'.
const test1: NS = 'morgning.breakfast' // works
console.log(namespaceEvent) // ["morgning.breakfast", "morgning.mingle", "evning.mingle", "evning.eat", "evning.party"]
查看 TS Playground:https://tsplay.dev/WJRV5W
【讨论】:
Here's a version usingflatMap
。打字是一样的,但实现有点短。
干得好@Aplet123 感谢分享。我倾向于使用reduce,但这更干净以上是关于打字稿转换 Object.entries 将派生字符串数组减少为文字类型的主要内容,如果未能解决你的问题,请参考以下文章