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

如何将指定答案转为不使用'any'类型的TypeScript深合并函数

无any类型的TypeScript深度合并实现

原代码的问题在于使用object类型导致类型信息丢失,且无法正确推导嵌套对象的合并类型。以下是改进后的实现,全程未使用any:

类型定义与工具函数

首先定义递归合并类型,用于推导合并后的对象结构:

// 递归合并两个对象的类型,保留嵌套结构
type MergeDeep<T, U> = T extends object 
  ? U extends object 
    ? {
        [K in keyof T | keyof U]: K extends keyof U 
          ? K extends keyof T 
            ? MergeDeep<T[K], U[K]> 
            : U[K]
          : T[K]
      }
    : U
  : U;

// 带类型谓词的对象判断函数,让TS能识别判断后的类型
export function isObject(item: unknown): item is Record<string, unknown> {
  return !!item && typeof item === "object" && !Array.isArray(item);
}

深度合并函数实现

通过泛型和函数重载,确保类型安全且返回类型精确:

// 函数重载:支持单个源对象
export function mergeDeep<T extends object, U extends object>(target: T, source: U): MergeDeep<T, U>;
// 函数重载:支持多个源对象
export function mergeDeep<T extends object, U extends object[]>(target: T, ...sources: U): MergeDeep<T, U[number]>;
// 核心实现
export function mergeDeep(target: object, ...sources: object[]): object {
  if (!sources.length) return target;
  const source = sources.shift();

  if (isObject(target) && isObject(source)) {
    for (const key in source) {
      const sourceValue = source[key];
      if (isObject(sourceValue)) {
        // 若目标对象当前key不存在或不是对象,先初始化空对象
        if (!isObject(target[key])) {
          Object.assign(target, { [key]: {} });
        }
        // 递归合并嵌套对象
        mergeDeep(target[key] as object, sourceValue);
      } else {
        // 非对象类型直接覆盖
        Object.assign(target, { [key]: sourceValue });
      }
    }
  }

  return mergeDeep(target, ...sources);
}

测试代码

const obj1 = {
  one: {
    two: {
      keep: "yes!",
      change: "should not see me",
    },

    three: {
      four: {
        keep: "yes!",
        change: "should not see me",
      },
    },
  },
};

const obj2 = {
  one: {
    two: {
      change: "NICE 1!!",
    },

    three: {
      four: {
        change: "NICE 2!!",
      },
    },
  },
};

// 此时mergeDeep的返回类型会被正确推导为合并后的结构
const result = mergeDeep(obj1, obj2);
console.log(JSON.stringify(result, null, 2));

关键改进点

  • 类型谓词:isObject函数添加类型断言,让TypeScript能在条件判断后识别对象类型,避免类型模糊
  • 递归泛型:MergeDeep类型递归处理嵌套对象,确保合并后的返回类型与实际结构一致
  • 函数重载:针对单个/多个源对象的场景分别定义重载,让调用时的类型推导更精准
  • 类型安全:全程使用unknown和泛型替代any,避免类型逃逸

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 15:57:20