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

如何深度合并泛型嵌套对象A与B,使共享属性仅关联A定义

解决TypeScript嵌套对象类型合并时保留上层定义的需求

需求说明

我们有两个结构相似的嵌套对象A和B,希望合并后得到的类型满足:

  • one.two.three同时包含A中的func1和B中的func2
  • 上层的one、two、three这些共享属性仅引用A的定义,IDE跳转时只指向A中的对应节点,而非同时显示A和B的两个定义

问题分析

直接使用交叉类型typeof A & typeof B虽然能让three包含两个函数,但每个嵌套属性(one、two、three)都会变成交叉类型,导致IDE跳转时出现多个定义选项,不符合需求。

解决方案

我们可以自定义一个递归类型工具,仅在最底层属性合并A和B的类型,上层属性完全保留A的定义:

1. 定义递归合并类型

// 递归遍历T的结构,仅在叶子节点合并T和U的对应属性,上层保留T的定义
type MergeDeepKeepRoot<T extends object, U extends object> = {
  [K in keyof T]: T[K] extends object 
    ? U[K] extends object 
      ? MergeDeepKeepRoot<T[K], U[K]> 
      : T[K]
    : T[K] & (K extends keyof U ? U[K] : never);
};

2. 应用类型并创建合并对象

// 使用as const让TypeScript保留精确的字面量类型
const A = {
  one: {
    two: {
      three: {
        func1: () => null,
      },
    },
  },
} as const;

const B = {
  one: {
    two: {
      three: {
        func2: () => null,
      },
    },
  },
} as const;

// 生成合并后的类型
type MergedType = MergeDeepKeepRoot<typeof A, typeof B>;

// 创建符合类型的合并对象
const C: MergedType = {
  one: {
    two: {
      three: {
        ...A.one.two.three,
        ...B.one.two.three,
      },
    },
  },
};

效果验证

  • 调用C.one.two.three.func1()和C.one.two.three.func2()均合法
  • 跳转one、two、three时,IDE只会指向A中的对应定义
  • 跳转func2时,会指向B中的原定义

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 08:31:02