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

如何用TypeScript实现支持多参数的对象合并函数?

TypeScript 实现支持任意数量参数的对象合并函数

问题背景

我已经写好了一个只能合并两个对象的函数,类型推断正常,鼠标悬停返回值能看到所有合并后的属性:

const mergeObjects = <T, U>(a: T, b: U): T & U => {
  const mergedObject = {}
  _.merge(mergedObject, a, b)
  return mergedObject as T & U
}

const a = {
  a: '1',
  b: '2',
}
const b = {
  c: '3',
  d: '4',
}
const c = mergeObjects(a, b)

现在想把这个函数改成能接收任意多个对象参数,但自己试的代码有问题——不仅逻辑上硬编码了参数,类型也没法正确推断返回值:

const mergeObjects = <T extends object>(...sources: T[]) => {
  const mergedObject = {}
  _.merge(mergedObject, a, b) // 这里写死了a和b,没用到传入的所有参数
  return mergedObject // 没有正确的返回类型标注
}

const a = {
  a: '1',
  b: '2',
}
const b = {
  c: '3',
  d: '4',
}
const d = {
  e: '5',
  f: '6',
}
const c = mergeObjects(a, b, d) // 没法看到合并后的完整属性类型

补充:用的是Lodash的_.merge,目的是封装它,返回新对象不修改原对象。

解决方法

要同时搞定任意参数支持和正确的类型推断,得从类型定义和函数逻辑两方面改:

1. 类型层面:把所有参数类型合并成交叉类型

用泛型元组来接收参数,再通过类型转换把参数的联合类型转成交叉类型,这样返回值就能正确包含所有对象的属性。

2. 逻辑层面:动态传入所有参数

把_.merge的参数改成扩展所有传入的sources,确保每个对象都被合并到新创建的空对象里。

最终可行代码:

// 辅助类型:把联合类型转成交叉类型
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;

const mergeObjects = <T extends object[]>(...sources: T): UnionToIntersection<T[number]> => {
  const mergedObject = {};
  // 把所有传入的对象都传给_.merge
  _.merge(mergedObject, ...sources);
  return mergedObject as UnionToIntersection<T[number]>;
}

// 测试用例
const a = { a: '1', b: '2' };
const b = { c: '3', d: '4' };
const d = { e: '5', f: '6' };
const c = mergeObjects(a, b, d);
// 现在鼠标悬停c,能看到它包含a、b、c、d、e、f所有属性

关键点说明

  • <T extends object[]>:限定传入的参数必须是对象组成的数组
  • T[number]:取出数组里所有元素的类型,形成一个联合类型
  • UnionToIntersection<T[number]>:把联合类型转换成交叉类型,也就是最终合并后的对象类型
  • _.merge(mergedObject, ...sources):动态传入所有参数,保证所有对象都被合并到新对象中

内容的提问来源于stack exchange,提问作者Islam Y-

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 21:22:52