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

如何为Object.assign实现更优的TypeScript类型推断?

解决TypeScript中Object.assign多源参数返回any的问题

TypeScript内置的Object.assign类型定义存在局限性:当传入的源对象数量超过4个时,返回值类型会退化为any,完全丧失了类型检查的作用。我们可以通过自定义类型推导逻辑来解决这个问题。

最优解决方案:递归合并元组类型实现精确推导

通过递归合并源参数的元组类型,我们可以让Object.assign支持任意数量的源对象,同时保持返回值类型的精确性:

// 递归合并元组内所有类型为交叉类型
type MergeSources<T extends object[]> = T extends [infer FirstSource, ...infer RestSources]
  ? FirstSource & MergeSources<RestSources>
  : {};

// 重新定义assign的类型
type TypedAssign = {
  <Target extends object, Sources extends object[]>(
    target: Target,
    ...sources: Sources
  ): Target & MergeSources<Sources>;
};

// 使用示例
const target = { id: 100 };
const source1 = { name: "Alice" };
const source2 = { age: 25 };
const source3 = { email: "alice@example.com" };
const source4 = { address: "Somewhere" };
const source5 = { phone: "123456789" };

const mergedObj = (Object.assign as TypedAssign)(target, source1, source2, source3, source4, source5);
// mergedObj的类型为:{ id: number } & { name: string } & { age: number } & { email: string } & { address: string } & { phone: string }

全局扩展内置类型(可选)

如果希望在整个项目中直接使用增强后的Object.assign,可以在全局类型声明文件(比如global.d.ts)中扩展ObjectConstructor:

declare global {
  interface ObjectConstructor {
    assign<Target extends object, Sources extends object[]>(
      target: Target,
      ...sources: Sources
    ): Target & MergeSources<Sources>;
  }
}

type MergeSources<T extends object[]> = T extends [infer F, ...infer R] ? F & MergeSources<R> : {};

// 确保这个文件被视为模块
export {};

方案原理

  • MergeSources类型通过递归遍历源对象的元组,将所有源对象的类型逐步合并为交叉类型;
  • 自定义的TypedAssign利用可变元组类型Sources extends object[]接收任意数量的源对象,最终返回目标类型与所有源类型的交叉组合,无论源对象数量多少,都能保持完整的类型信息。

这种方案彻底解决了原内置类型的局限性,让Object.assign在任何参数数量下都能提供可靠的类型检查与推导。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 06:40:04