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

如何在TypeScript中编写符合对象合并逻辑的通用泛型函数

错误原因

  • 你定义的ExtendRec将Y声明为调用侧传入的泛型参数,相当于约定该类型的函数返回值由调用方决定,只要符合Y extends X/Y extends Rec约束即可,但你的实现是固定返回「输入对象+指定新增属性」的交叉类型,和调用方可能传入的任意Y类型不匹配,因此触发类型错误。
  • 移除类型标注后TS会自动推导每个函数的泛型签名,自动把返回值识别为输入类型和新增属性的交叉类型,因此运行正常。

解决方案

如果要约束所有「接收一个对象,返回该对象扩展固定属性后的新对象」的函数,需要把固定扩展的属性类型作为ExtendRec的泛型参数,在定义具体函数时就确定,而不是留到调用时传入:

type Rec = Record<string, unknown>
// Extra是要扩展的固定属性的类型,定义函数时传入确定
type ExtendRec<Extra extends Rec> = <X extends Rec>(x: X) => X & Extra

// 定义时指定对应要扩展的属性类型
const addA: ExtendRec<{ a: string }> = (x) => ({ ...x, a: 'a' })
const addB: ExtendRec<{ b: string }> = (x) => ({ ...x, b: 'b' })
const addC: ExtendRec<{ c: string }> = (x) => ({ ...x, c: 'c' })

const blank = {} 
const a = addA(blank) // 类型为 { a: string }
const ab = addB(a) // 类型为 { a: string, b: string }
const abc = addC(ab) // 类型为 { a: string, b: string, c: string }

如果是要定义和{...a, ...b}完全等价的双参数合并函数,直接用以下类型即可:

type MergeRec = <X extends Rec, Y extends Rec>(a: X, b: Y) => X & Y

const merge: MergeRec = (a, b) => ({ ...a, ...b })

补充:如果你的扩展逻辑允许新增属性覆盖原对象的同名属性,可以把ExtendRec定义修改为以下形式,类型计算会更严谨:

type ExtendRec<Extra extends Rec> = <X extends Rec>(x: X) => Omit<X, keyof Extra> & Extra

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 16:45:04