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

如何定义TypeScript类型将函数记录转换为重载函数签名?

TypeScript Trait函数类型定义解决方案

要实现Trait返回的函数能够精准匹配传入对象中每个方法的参数,同时对无效参数触发类型错误,可通过映射类型生成函数联合的方式解决:

核心类型定义

type TraitType<TS extends { [key: string]: (...args: any) => any }> = 
  { [K in keyof TS]: (args: Parameters<TS[K]>[0]) => ReturnType<TS[K]> }[keyof TS];

完整实现代码

type TraitType<TS extends { [key: string]: (...args: any) => any }> = 
  { [K in keyof TS]: (args: Parameters<TS[K]>[0]) => ReturnType<TS[K]> }[keyof TS];

function Trait<TS extends { [key: string]: (...args: any) => any }>(ts: TS): TraitType<TS> { 
  // 实际逻辑需根据需求完善,此处仅作类型兼容的示例实现
  return ((args: any) => {
    if ('left' in args && 'right' in args) return ts.Alt(args);
    if ('value' in args) return ts.Char(args);
    if ('first' in args && 'second' in args) return ts.Cat(args);
    throw new Error('Invalid argument structure');
  }) as TraitType<TS>;
}

const printLang = Trait({
  Alt: ({ left, right }: { left: string; right: string }) => `${left}|${right}`,
  Char: ({ value }: { value: string }) => `${value}`,
  Cat: ({ first, second }: { first: string; second: string }) => `${first},${second}`
});

// 合法调用:匹配对应方法的参数签名
printLang({ left: 'foo', right: 'bar' });
printLang({ value: 'baz' });
printLang({ first: 'qux', second: 'quux' });

// 非法调用:触发类型错误
printLang({ error: '?' }); // 类型检查报错:对象字面量只能包含已知属性,'error' 不在允许的参数类型中

方案说明

  • TraitType通过映射类型遍历传入对象的每个方法键,为每个方法生成专属的函数类型(参数为方法的第一个入参,返回值为方法的返回类型)。
  • 最后通过[keyof TS]将所有专属函数类型提取为联合类型,TypeScript在调用时会自动匹配联合中的有效签名,确保参数与对应方法严格匹配。

对比原问题的解决点

  1. 替代TS[keyof TS]:避免仅取第一个函数定义的问题,保留所有方法的类型信息。
  2. 替代(self: TS[keyof TS]) => ...:不再使用参数联合类型,而是为每个方法绑定专属参数,调用时能精准匹配。
  3. 替代(...args: Parameters<TS[keyof TS]>) => ...:避免参数变成所有方法参数的交集,确保每个调用只需要符合某一个方法的参数结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 10:00:55