You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 02:22:02