如何合并两个泛型对象类型的属性?TypeScript类型疑问
这个问题我之前也遇到过!TypeScript 默认的交叉类型 A & B 确实没法准确反映 Object.assign 的覆盖行为——毕竟交叉类型里同名属性是取两者的交集,而实际运行时后面的对象会直接覆盖前面的同名属性。
要解决这个问题,我们可以自己构造一个符合 Object.assign 行为的合并类型,核心思路就是:保留 B 的所有属性,再加上 A 中那些 B 没有的属性。
首先定义一个工具类型 Merge:
type Merge<A extends object, B extends object> = Omit<A, keyof B> & B;
这里 Omit<A, keyof B> 会把 A 中所有在 B 里存在的键剔除掉,然后和 B 做交叉类型,这样就完美实现了「B 覆盖 A 同名属性,同时保留 A 独有属性」的效果。
接下来把你的函数返回类型指定为这个 Merge 类型,再用类型断言告诉 TypeScript 实际返回值的类型(因为 Object.assign 的默认返回类型还是 A & B):
function foo<A extends object, B extends object>(a: A, b: B): Merge<A, B> { return Object.assign({}, a, b) as Merge<A, B>; }
现在测试你提到的调用场景:
const result = foo({a: 42}, {b: "foo", a: "bar"}); // result 的类型会是 { a: string; b: string },完全符合运行时的实际结果
再举个更复杂的例子验证一下:
const result2 = foo({a: 42, c: true}, {b: "foo", a: "bar"}); // result2 的类型是 { a: string; b: string; c: boolean },A 独有的 c 属性被保留,a 属性被 B 的类型覆盖
这个方案完全贴合 Object.assign 的运行时行为,类型推导也准确。
内容的提问来源于stack exchange,提问作者Jomik
相关产品推荐
相关产品推荐

