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

如何从TypeScript重载函数接口中提取事件名称联合类型?

从重载的on函数中提取事件名称联合类型

这确实是TypeScript处理重载函数时的一个常见坑——当你直接用infer提取重载函数的参数时,默认只会匹配最后一个重载签名,这就是为什么你只得到了eventName8。下面是解决这个问题的具体方案:

解决方案

我们需要显式地匹配on函数的所有重载签名,把每个重载的参数元组合并成联合类型,再从中提取事件名称:

// 辅助类型:提取重载函数的所有参数元组的联合类型
type GetOverloadArgs<T> = 
  // 匹配8个重载的情况(对应你的IEvents中的on函数)
  T extends {
    (...args: infer A): void;
    (...args: infer B): void;
    (...args: infer C): void;
    (...args: infer D): void;
    (...args: infer E): void;
    (...args: infer F): void;
    (...args: infer G): void;
    (...args: infer H): void;
  } ? A | B | C | D | E | F | G | H : 
  // 如果重载数量更少,可以继续添加匹配分支
  T extends {
    (...args: infer A): void;
    (...args: infer B): void;
    (...args: infer C): void;
    (...args: infer D): void;
    (...args: infer E): void;
    (...args: infer F): void;
    (...args: infer G): void;
  } ? A | B | C | D | E | F | G :
  T extends {
    (...args: infer A): void;
    (...args: infer B): void;
    (...args: infer C): void;
    (...args: infer D): void;
    (...args: infer E): void;
    (...args: infer F): void;
  } ? A | B | C | D | E | F :
  never;

// 提取IEvents中on函数的所有事件名称联合类型
export type TEventExtension<T extends IEvents> = 
  GetOverloadArgs<T['on']> extends [infer N, ...any[]] ? N : never;

// 测试验证
type EventNames = TEventExtension<IEvents>;
// EventNames 类型为:'eventName1' | 'eventName2' | 'eventName3' | 'eventName4' | 'eventName5' | 'eventName6' | 'eventName7' | 'eventName8'

为什么之前的方案无效?

你之前的代码中,TEventListenerName<T>的类型推断逻辑:

type TEventListenerName<T> = T extends (name: infer N, listener: (obj?: infer E) => void) => void ? N : never;

只会匹配T的最后一个重载签名。TypeScript的类型系统在处理重载函数时,不会自动将所有重载签名转换为联合类型,所以直接用单一层级的infer只能拿到最后一个重载的参数。

扩展说明

如果外部模块的IEvents中on函数的重载数量发生变化,你只需要调整GetOverloadArgs中的匹配分支层数即可,这个方法不需要复制外部的接口定义,完全基于原接口自动推导。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:33:24