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

TypeScript中如何将对象数组的键映射到另一对象类型的键?

如何精确关联res1与res2的TypeScript类型映射

问题场景

现有API返回的两个数据结构res1和res2存在关联:res1是任意长度的对象数组,每个元素的name字段对应res2中的一个字段(res2包含固定字段AlwaysPresent1/AlwaysPresent2),这些关联字段的类型固定为SubType。当前使用索引签名[k: string]: subType | string | number描述res2,但类型过于宽泛,希望找到更精确的类型定义方式。

示例代码:

const res1: res1Type = [
  {
    name: "FieldNameA",
    value: 123
  },
  {
    name: "FieldNameB",
    value: 123
  }
];
const res2: res2Type = {
  AlwaysPresent1: "test",
  AlwaysPresent2: 1,
  FieldNameA: {
    field1: 1,
    field2: 2
  },
  FieldNameB: {
    field1: 1,
    field2: 2
  }
};

type res1Type = {
  name: string;
  value: number;
}[];
type res2Type = {
  AlwaysPresent1: string;
  AlwaysPresent2: number;
  [k: string]: subType | string | number;
};
type subType = {
  field1: number;
  field2: number;
};

解决方案:泛型+映射类型

可以通过泛型结合映射类型,直接将res1中name字段的具体值映射到res2的字段定义中,完全替代宽泛的索引签名:

  1. 先定义基础类型:
type SubType = {
  field1: number;
  field2: number;
};

type Res1Item = {
  name: string;
  value: number;
};
  1. 定义依赖res1类型的res2泛型类型:
// 泛型T接收res1的只读数组类型,确保能捕获name的具体字面量
type Res2Type<T extends ReadonlyArray<Res1Item>> = {
  // 固定字段的类型定义
  AlwaysPresent1: string;
  AlwaysPresent2: number;
} & {
  // 映射res1中所有name字段为SubType类型
  [K in T[number]['name']]: SubType;
};
  1. 实际使用时,让TypeScript捕获res1的具体类型:
// 使用as const让TS捕获name的具体字符串字面量,而非宽泛的string
const res1 = [
  { name: "FieldNameA", value: 123 },
  { name: "FieldNameB", value: 123 }
] as const;

// 提取res1的类型
type Res1Type = typeof res1;
// 生成对应的res2类型
type Res2FinalType = Res2Type<Res1Type>;

// 此时res2的类型完全精确:固定字段必须存在,FieldNameA/B必须是SubType,无法赋值为string/number
const res2: Res2FinalType = {
  AlwaysPresent1: "test",
  AlwaysPresent2: 1,
  FieldNameA: { field1: 1, field2: 2 },
  FieldNameB: { field1: 1, field2: 2 }
};

方案优势

  • 类型精确:res2的动态字段严格对应res1中name的具体值,类型固定为SubType,避免了索引签名带来的联合类型模糊问题
  • 类型安全:如果res1的name字段变更,res2的类型会自动同步约束,减少手动维护的错误
  • 扩展性强:新增res1元素时,res2的类型会自动包含对应的字段定义

更新说明

已采用上述方案并将Res1Type显式声明为Readonly:

type Res1Type = Readonly<{
    name: string;
    value: number;
}[]>;

这一修改确保了res1数组的不可变性,同时让TypeScript更稳定地捕获数组元素的类型信息,进一步提升类型约束的可靠性。

内容的提问来源于stack exchange,提问作者Danny S.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 21:28:39