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

如何在TypeScript中提取数组接口合并为联合类型并实现动态类型函数

让TypeScript对象数组合并函数返回动态推导类型的实现方案

问题分析

你的unit函数当前无法正确推导返回值类型,原因在于泛型T extends object会将数组元素推断为输入对象的联合类型,而返回值默认被推断为空对象{},无法体现对象合并后的属性结构。

解决方案

我们需要让TypeScript保留数组中每个对象的具体类型,并将这些类型合并为交叉类型(模拟对象展开后的属性集合)。以下是两种实现方式:

方式1:递归合并元组类型

通过递归遍历元组中的每个对象类型,逐步合并为交叉类型:

// 递归合并元组中的所有对象类型
type MergeObjects<T extends object[]> = T extends [infer First, ...infer Rest]
  ? First extends object
    ? Rest extends object[]
      ? First & MergeObjects<Rest>
      : First
    : MergeObjects<Rest>
  : {};

function unit<T extends object[]>(arr: [...T]): MergeObjects<T> {
  let obj = {} as MergeObjects<T>;
  arr.forEach(val => {
    obj = { ...obj, ...val };
  });
  return obj;
}

// 测试示例
const a = { name: "l" };
const b = { age: 1 };
const c = { gender: "male" };

const person = unit([a, b, c]); 
// 自动推断类型为:{ name: string; } & { age: number; } & { gender: string; }
// TypeScript会自动简化为:{ name: string; age: number; gender: string; }

方式2:联合类型转交叉类型(更简洁)

利用TypeScript的条件类型特性,将元组元素的联合类型转换为交叉类型:

// 将联合类型转换为交叉类型的工具类型
type UnionToIntersection<U> = 
  (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) 
    ? I 
    : never;

function unit<T extends object[]>(arr: [...T]): UnionToIntersection<T[number]> {
  let obj = {} as UnionToIntersection<T[number]>;
  arr.forEach(val => {
    obj = { ...obj, ...val };
  });
  return obj;
}

// 测试示例
const a = { name: "l" };
const b = { age: 1 };

const person = unit([a, b]); 
// 推断类型为:{ name: string; } & { age: number; },等价于合并后的对象类型

关键细节说明

  • 使用[...T]作为参数类型:确保TypeScript将输入数组推断为元组类型,而非宽泛的object[],这样才能保留每个元素的具体类型信息。
  • 交叉类型的作用:交叉类型A & B会将两个对象的属性合并,若存在重复属性,后面的类型会覆盖前面的,这和JavaScript中对象展开{...a, ...b}的行为完全一致。

内容的提问来源于stack exchange,提问作者why do i have so much question

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 00:35:30