You need to enable JavaScript to run this app. TypeScript 如何为对象方法定义带类型、保签名的包装函数
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript 如何为对象方法定义带类型、保签名的包装函数

类型报错的根本原因

你现在写的wrapper触发TS校验失败,问题出在泛型的设计逻辑上:

  • 泛型T extends keyof myFunctions的取值范围是'one' | 'two' | 'echo'三个键的联合,TS在检查函数内部代码时,不会把你传入的func参数和T做一对一的收窄绑定,只会把T覆盖的所有可能值展开成联合类型做校验
  • 这时候myFunctions[T]会被推导为(() => number) | ((str: string) => string)的联合类型,对应的Parameters<myFunctions[T]>就变成了[] | [str: string]的参数数组联合
  • 受TS参数逆变规则的限制,联合类型的函数能接收的入参,必须是所有成员函数入参的交集,和推导出的参数数组联合类型根本不兼容,自然就会报类型错误
正确的实现方案

其实完全不需要从对象的键名反推方法类型,直接让泛型捕获被传入函数的完整签名就行,这样TS会自动和传入的函数做精准绑定,从根源上避免联合类型扩散的问题:

// 定义可被包装的函数类型边界
type AnyFunction = (...args: any[]) => any;

const wrapper = <F extends AnyFunction>(
  func: F
) => {
  // 返回的包装函数会自动继承原函数的参数、返回值完整签名
  return (...args: Parameters<F>): ReturnType<F> => {
    return func(...args);
  };
};

如果需要限制wrapper只能接收myFunctions对象里定义的方法,不能传入其他任意函数,可以把泛型的约束范围收窄为myFunctions里所有方法的类型联合:

const wrapper = <F extends myFunctions[keyof myFunctions]>(
  func: F
) => (...args: Parameters<F>): ReturnType<F> => func(...args);
实际调用效果

实现完成后,根本不需要手动给wrapper传键名当泛型,TS会自动根据你传入的方法推导完整签名,完全匹配你预期的使用场景:

  • 传myFunctions.one,返回的包装函数会自动校验为「无入参、返回number」
  • 传myFunctions.echo,返回的包装函数会自动校验为「接收1个string类型入参、返回string」

顺带一提,你之前尝试的手动传入键名当泛型的写法是完全多余的:把对应方法传给wrapper时,TS会自动完成精准的类型推导,手动指定键名反而容易引发类型不匹配。

直接按以下方式调用就能通过类型校验:

wrapper(myFunctions.one)()
wrapper(myFunctions.echo)('hello')

如果出现传参不匹配的情况——比如给echo方法传数字、给one方法多塞参数,TS都会准确触发报错,和原方法的类型校验规则完全一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.03 08:54:03