TypeScript转换数组元素为对象时返回类型推断错误
TypeScript类型推断问题:数组转对象时类型丢失
问题描述
我编写了一个将数组元素转换为对象的TypeScript函数,代码如下:
function mapToCreateObjects<K extends keyof U, T, U extends Record<K, T[]>>(obj: U, key: K): Record<K, { create: T }[]> { return { [key]: obj[key].map((item) => ({ create: item })), } as Record<K, { create: T }[]>; } const data = { fruits: ['apple', 'banana', 'cherry'], vegetables: [1, 2, 3], }; const transformedFruits = { ...mapToCreateObjects(data, 'fruits'), ...mapToCreateObjects(data, 'vegetables'), };
期望transformedFruits的类型为:
{ fruits: { create: string }[], vegetables: { create: number }[] }
但TypeScript却将两者都推断为{ create: unknown }[]。
问题原因
- 泛型参数顺序不合理:
T放在U之前,TypeScript无法从obj[key]的数组类型反向推导T的具体类型,只能默认推断为unknown。 - 类型断言掩盖问题:返回值使用
as Record<K, { create: T }[]>强行指定类型,让TypeScript跳过了更精确的类型检查,无法修正T的推断错误。
修复方案
调整泛型参数顺序,利用条件类型infer直接从数组类型中提取元素类型,不需要显式声明T:
function mapToCreateObjects<U, K extends keyof U>( obj: U, key: K ): { [P in K]: { create: U[P] extends (infer T)[] ? T : never }[] } { return { [key]: obj[key].map(item => ({ create: item })) } as any; } const data = { fruits: ['apple', 'banana', 'cherry'], vegetables: [1, 2, 3], }; const transformedFruits = { ...mapToCreateObjects(data, 'fruits'), ...mapToCreateObjects(data, 'vegetables'), };
现在transformedFruits的类型会被正确推断为:
{ fruits: { create: string }[], vegetables: { create: number }[] }
更简洁的写法(TypeScript 4.7+适用)
如果使用较新版本的TypeScript,还可以简化函数,让返回类型自动推导:
function mapToCreateObjects<U, K extends keyof U>(obj: U, key: K) { return { [key]: obj[key].map(item => ({ create: item })) } as const; }
这种写法下,每次调用函数都会返回精确的字面量类型,展开后同样能得到正确的transformedFruits类型。
内容的提问来源于stack exchange,提问作者Mathieu Lordon
相关产品推荐
相关产品推荐

