为何TypeScript会为计算属性的值推断出异常类型?
TypeScript计算属性的类型推断异常排查与解决
我第一次编写以下函数时遇到了意外行为:
function splatIfDefinedBad<K extends string, V>( key: K, value: V ): Partial<Record<K, V>> { if (value === undefined) { return {} } return { [key] : value } }
TypeScript编译器抛出错误:
Type '{ [x: string]: V & ({} | null); }' is not assignable to type 'Partial<Record<K, V>>.'
我无法理解value的推断类型中& ({} | null)部分的来源。
换一种对象构建方式后,问题得以解决:
function splatIfDefinedGood<K extends string, V>( key: K, value: V ): Partial<Record<K, V>> { if (value === undefined) { return {} } const output: Partial<Record<K, V>> = {}; output[key] = value; return output; }
一开始我以为是计算属性的特性导致{ [key]: value }可能生成{ [key]: null },即便类型V不包含null。
后来我注意到{} | null表示“除undefined外的任意值”(因为{}类型本身代表“除null或undefined外的任意值”),因此推测这和TypeScript的类型推断机制有关?它尝试将V收窄为排除undefined的类型,但在处理类似V & Not<undefined>(假设存在该映射类型)时无法正确统一类型?而splatIfDefinedGood的写法是反向操作——在已知类型的对象上添加K对应的V类型属性,而非从“任意值”收窄到“非undefined值”?
编辑补充:
正如@ruakh指出,问题根源只是K被拓宽成了string!以下写法同样可以正常运行:
function splatIfDefined2<K extends string, V>( key: K, value: V ): Partial<Record<K, V>> { if (value === undefined) { return {} } return { [key as K] : value } as { [k in K]: V & ({} | null) } }
内容的提问来源于stack exchange,提问作者PoolOfPeas
相关产品推荐
相关产品推荐

