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

如何让TypeScript的mergeProps函数返回包含所有属性的精确类型?

如何让TypeScript的mergeProps函数返回包含所有属性的精确类型?

我来帮你解决这个TypeScript类型推断的问题~先看你给出的代码场景:

const obj1 = { prop1: 'v1', prop2: 'v2' };
const obj2 = { prop3: 'v3', prop4: 'v4' };

// 这个merged变量有精确的类型:{ prop1: string; prop2: string; prop3: string; prop4: string; }
const merged = {...obj1, ...obj2};

// 但这个mergeProps函数返回的只是宽泛的object类型,导致mergedWithHandler.prop1会被TS判定为无效
const mergeProps = (targets: Array<object>) => targets.reduce((acc, target) => ({ ...acc, ...target }), {});
const mergedWithHandler = mergeProps([obj1, obj2]);

问题出在Array<object>这个类型上——它太宽泛了,TypeScript没法从中捕获到每个对象的具体属性信息,所以只能返回最基础的object类型。要让mergeProps返回包含所有属性的精确类型,我们需要用泛型来精准捕获每个输入对象的类型,再让TS计算出合并后的结果类型。

下面给你两种可行的解决方案:

方案一:自定义Merge类型辅助合并

首先定义一个用来模拟数组reduce逻辑的类型工具,它会递归合并所有传入对象的类型:

type Merge<T extends object[]> = T extends [infer First, ...infer Rest]
  ? First extends object
    ? Merge<Rest> extends object
      ? { ...First, ...Merge<Rest> }
      : First
    : Merge<Rest>
  : {};

然后重写mergeProps函数,用泛型约束输入数组的类型,并指定返回值为Merge后的精确类型:

const mergeProps = <T extends object[]>(targets: [...T]): Merge<T> => {
  return targets.reduce((acc, target) => ({ ...acc, ...target }), {} as Merge<T>);
};

现在测试一下,mergedWithHandler的类型会被正确推断成和merged完全一致的精确类型,访问mergedWithHandler.prop1也不会再报错啦。

方案二:利用内置类型简化实现

如果你不想自定义Merge类型,也可以用TypeScript的内置类型能力来简化代码:

const mergeProps = <T extends object[]>(...targets: [...T]): T[number] extends infer U ? { [K in keyof U]: U[K] } : never => {
  return targets.reduce((acc, target) => ({ ...acc, ...target }), {} as any);
};

这里的[...T]是为了让TypeScript能推断出数组中每个元素的具体类型(而不是统一的联合类型),T[number]会取出所有对象类型的联合,最后通过索引类型把它们合并成一个包含所有属性的对象类型。

核心思路其实就是:别用宽泛的object类型去约束输入,而是用泛型精准捕获每个对象的类型信息,让TypeScript能基于这些信息计算出合并后的精确类型。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 12:02:59