TypeScript元组数组转对象类型错误原因及遍历keyof Entries实现方案
问题1:第一种实现错误的原因
核心是映射类型的右侧值类型不会随重映射的键自动窄化:
当你遍历keyof Entries时,Index是所有数组键的联合类型(不仅包含"0"、"1"这类元组元素索引,还包含length、push等数组原型属性名)。在计算值类型EntryValue<Entries[Index]>时,Entries[Index]是所有元组元素的联合(["a", number] | ["b", string]),而EntryValue是分布式条件类型,对联合类型计算后得到的是所有值类型的联合number | string,因此所有键的值都被推导为这个联合类型,而不是和键对应的单独类型。
问题2:第二种简化实现报错的原因
keyof Entries包含了大量非元组元素的索引键(比如length、slice等数组原型属性),这些键对应的Entries[Index]类型不是二元元组(比如length对应的值类型是number),无法用数字0/1进行索引,TypeScript检测到存在非法索引的可能性,因此直接抛出编译错误。
问题3:遍历keyof Entries的正确实现
存在,可以通过条件类型过滤无效索引、窄化类型,实现和遍历Entries[number]一致的效果,示例如下:
type ObjectKey = string | number; type ObjFromEntriesWithKeyof<Entries extends [ObjectKey, unknown][]> = { [Index in keyof Entries as Entries[Index] extends [infer K extends ObjectKey, unknown] ? K : never ]: Entries[Index] extends [ObjectKey, infer V] ? V : never }; // 测试:得到 {a: number; b: string} 正确结果 type Test2 = ObjFromEntriesWithKeyof<[["a", number], ["b", string]]>
原理是:对每个Index,先用条件类型判断Entries[Index]是否为合法二元元组,如果是就取第一个元素作为键,否则返回never过滤该索引;值类型也通过条件类型窄化后取第二个元素,规避非法索引的报错问题。
内容的提问来源于stack exchange,提问作者JKillian
相关产品推荐
相关产品推荐

