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

TypeScript中动态合并多组IndexedObject数组的类型定义问题

解决方案

类型定义与辅助工具

先明确IndexedObject基础类型,再通过辅助类型处理多类型的属性合并:

// 基础类型:为原始对象附加索引追踪属性_i
type IndexedObject<T> = T & { _i: number };

// 从IndexedObject中提取原始对象的类型
type ExtractIndexedType<T> = T extends IndexedObject<infer U> ? U : never;

// 将联合类型转换为交叉类型,实现多类型属性的合并
type UnionToIntersection<U> = 
  (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) 
    ? I 
    : never;

合并函数实现

利用可变元组泛型捕获所有输入数组的类型,让返回类型动态包含所有输入类型的键:

function mergeByIndex<T extends IndexedObject<any>[]>(...arrays: [...T]): 
  (UnionToIntersection<ExtractIndexedType<T[number]>> & { _i: number })[] 
{
  // 按_i分组并合并属性的核心逻辑
  const indexMap = new Map<number, Record<string, unknown>>();

  for (const arr of arrays) {
    for (const item of arr) {
      const existing = indexMap.get(item._i) ?? {};
      // 合并现有对象与当前元素的属性,保留索引_i
      indexMap.set(item._i, { ...existing, ...item });
    }
  }

  return Array.from(indexMap.values()) as ReturnType<typeof mergeByIndex<T>>;
}

测试示例

// 定义不同结构的原始业务类型
type User = { name: string };
type Order = { orderId: number };
type Address = { city: string };

// 构造带索引标记的数组
const users: IndexedObject<User>[] = [{ name: "Alice", _i: 1 }, { name: "Bob", _i: 2 }];
const orders: IndexedObject<Order>[] = [{ orderId: 1001, _i: 1 }, { orderId: 1002, _i: 3 }];
const addresses: IndexedObject<Address>[] = [{ city: "Beijing", _i: 2 }, { city: "Shanghai", _i: 3 }];

// 合并后类型自动包含所有输入类型的属性
const merged = mergeByIndex(users, orders, addresses);
// merged[0] 类型:User & Order & { _i: number } → 包含name、orderId、_i
// merged[1] 类型:User & Address & { _i: number } → 包含name、city、_i
// merged[2] 类型:Order & Address & { _i: number } → 包含orderId、city、_i

关键说明

  • 可变元组泛型[...T]确保TypeScript能准确推断所有输入数组的元素类型,避免类型丢失。
  • UnionToIntersection是实现动态属性合并的核心:将多个输入类型的联合转换为交叉类型,让返回的对象类型自动包含所有输入类型的键。
  • 类型断言用于绕过TypeScript对Map值的类型限制,保证最终返回类型与定义一致。

内容的提问来源于stack exchange,提问作者Amir

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 18:01:24