如何深度合并泛型嵌套对象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
相关产品推荐
相关产品推荐

