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

如何在TypeScript联合类型中替换fn方法的参数类型?

替换联合类型中函数的参数类型,保留原有联合结构

库提供的类型定义

// given typings of library
type t1 = string
type t2 = number
type t3 = { [key: string]: number | string | boolean | Array<string | number> | undefined }

interface i0 {
  aa: t1
  fn?: (arg: t3) => boolean
}

interface i1 extends i0 {
    ba: t2,
    bb: t2
}

interface i2 extends i0 {
    ca: t2,
    cb: t2
}

type union = i1 | i2 

自定义类型及问题示例

// my typings
type t4 = { prop1: string, prop2: number }
type myfn<T> = { fn?: ((arg: T) => boolean) }
type mytype<T> = myfn<T> | Omit<union, 'fn'>
type myNonUnionType<T> = myfn<T> | Omit<i1, 'fn'>

// implementation examples
let obj1: union = {
  aa: 'hello',
  ba: 3,
  bb: 4,
  fn: (arg) => arg.prop1 === arg.prop2.toString()  // error: possible undefined
}

let obj2: mytype<t4> = {
  aa: 'hello',
  ba: 2, // error: ba does not exist
  bb: 3,
  fn: (arg) => arg.prop1 === arg.prop2.toString()
}

let obj3: mytype<t4> = {
  aa: 'hello',
  ca: 2, // error: ca does not exist
  cb: 3,
  fn: (arg) => arg.prop1 === arg.prop2.toString()
}

let obj4: myNonUnionType<t4> = { // works, but only without union
  aa: 'hello',
  ba: 2,
  bb: 3,
  fn: (arg) => arg.prop1 === arg.prop2.toString()
}

问题原因

你定义的mytype<T>是把「仅包含自定义fn的类型」和「移除了fn的原联合成员」做联合。但当你编写同时拥有原联合成员属性(比如ba/ca)和自定义fn的对象时,这个对象既不属于myfn<T>(多了额外属性),也不属于Omit<union, 'fn'>(多了fn属性),导致TypeScript判定属性不存在。

解决方案

不需要拆分fn为独立分支,直接给原联合类型的每个成员单独替换fn的参数类型即可,用工具类型实现:

// 工具类型:替换目标类型中fn的参数为指定类型
type ReplaceFnParam<OriginalType, NewParam> = Omit<OriginalType, 'fn'> & {
  fn?: (arg: NewParam) => boolean
}

// 对原联合类型的每个成员应用参数替换
type mytype<T> = ReplaceFnParam<union, T>

验证效果

// 正常兼容i1结构+自定义fn参数
let obj2Fix: mytype<t4> = {
  aa: 'hello',
  ba: 2,
  bb: 3,
  fn: (arg) => arg.prop1 === arg.prop2.toString() // 无错误,arg类型为t4
}

// 正常兼容i2结构+自定义fn参数
let obj3Fix: mytype<t4> = {
  aa: 'hello',
  ca: 2,
  cb: 3,
  fn: (arg) => arg.prop1 === arg.prop2.toString() // 无错误,arg类型为t4
}

// 也支持省略fn的场景
let obj5: mytype<t4> = {
  aa: 'hello',
  ba: 5,
  bb: 6
}

这个方案的核心是保留原联合类型的结构,只针对每个成员的fn属性做参数类型替换,完美解决联合类型兼容问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 22:21:01