如何在将对象数组合并为数组对象时实现正确TypeScript类型标注
修复TypeScript reduce遍历联合键时的类型错误
你的代码逻辑没问题,但TypeScript的类型推断在处理联合类型的键时,无法自动关联每个键对应的具体值类型,导致出现string | number无法赋值给never的错误。以下是两种可靠的修复方案:
方案一:使用泛型函数明确类型关联
通过泛型函数将每个键的类型具体化,让编译器能识别prev[key]和current[key]的类型匹配关系:
type A = { foo: number, bar: string } type B = { [key in keyof A]: Array<A[key]> } const a: A[] = [ { bar: '42', foo: 42 }, { bar: '1337', foo: 1337 } ] // 泛型函数约束键与值的类型对应关系 const pushKeyValue = <K extends keyof A>(acc: B, item: A, key: K) => { acc[key].push(item[key]); }; const b: B = a.reduce((prev, current) => { (Object.keys(current) as (keyof A)[]).forEach(key => pushKeyValue(prev, current, key)); return prev; }, { foo: [], bar: [] } as B)
方案二:直接在回调中添加类型断言
如果不想额外定义函数,也可以在push时给数组添加类型断言,明确其对应的值类型:
const b: B = a.reduce((prev, current) => { (Object.keys(current) as (keyof A)[]).forEach(key => { // 断言数组类型为当前key对应的值类型数组 (prev[key] as Array<A[typeof key]>).push(current[key]); }); return prev; }, { foo: [], bar: [] } as B)
错误原因解析
当key是keyof A的联合类型时,TypeScript会把prev[key]推断为Array<number> | Array<string>,current[key]推断为number | string。此时编译器无法保证current[key]的类型和prev[key]的数组元素类型完全匹配,就会将数组元素类型推断为never(因为number & string不存在交集),从而抛出赋值错误。
泛型函数的方式更推荐,因为它能在不破坏类型安全的前提下,清晰地维护键与值的类型关联,尤其适合属性较多的复杂类型。
内容的提问来源于stack exchange,提问作者s4pfyr
相关产品推荐
相关产品推荐

