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

如何将联合类型约束为特定类型?解决TypeScript函数apply报错

TypeScript联合类型函数包装报错的解决方法

以下是用户提供的代码:

type MyMap = {
  a: () => void
  b: (s: string) => void
  c: (n: number) => void
}
type MyKey = keyof MyMap
function wrapper(fn: MyMap[MyKey]) {
  return async function(...arg: Parameters<MyMap[MyKey]>) {
    await Promise.resolve();
    fn.apply(null, arg);
  }
}

运行时TypeScript抛出错误:

The 'this' context of type '(() => void) | ((s: string) => void) | ((n: number) => void)' is not assignable to method's 'this' of type '(this: null) => void'.
Type '(s: string) => void' is not assignable to type '(this: null) => void'.
Target signature provides too few arguments. Expected 1 or more, but got 0.

用户认为逻辑上fn与arg匹配,需要解决该类型报错。

报错原因

问题核心在于联合类型的函数调用限制:MyMap[MyKey]是三个函数的联合类型,Parameters<MyMap[MyKey]>会生成[] | [string] | [number]的联合参数列表。TypeScript对联合类型函数的调用有严格规则——只有当传入的参数能被所有联合成员接受时才合法,显然这里无法满足(比如给需要string的函数传空参数不被允许),同时apply的this绑定也因联合类型签名不兼容触发报错。

解决方案:泛型约束实现类型安全匹配

通过泛型捕获具体的键类型,让函数与参数列表严格对应,避免使用模糊的联合类型:

type MyMap = {
  a: () => void
  b: (s: string) => void
  c: (n: number) => void
}
type MyKey = keyof MyMap

function wrapper<K extends MyKey>(fn: MyMap[K]) {
  return async function(...arg: Parameters<MyMap[K]>) {
    await Promise.resolve();
    fn.apply(null, arg);
  }
}

原理说明

泛型K会锁定传入fn对应的具体键(比如'a'、'b'或'c'),此时MyMap[K]变为单个确定的函数类型,Parameters<MyMap[K]>也会对应生成该函数的参数列表。fn与arg的类型完全匹配,TypeScript能正确完成类型校验,报错自然消除。

备选方案:类型断言(不推荐)

若暂时不想使用泛型,可通过类型断言跳过类型检查,但这会丢失TypeScript的类型安全保障:

function wrapper(fn: MyMap[MyKey]) {
  return async function(...arg: Parameters<MyMap[MyKey]>) {
    await Promise.resolve();
    (fn as (...args: any[]) => void).apply(null, arg);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 04:38:18