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

如何在泛型事件订阅函数中推断重载方法的类型?

泛型事件订阅函数的类型推断问题解决

我需要实现一个泛型subscribe函数,参数包括事件名称、事件处理函数和目标事件发射器,核心要求是自动推断处理函数的参数类型——比如传入Node.js的process对象和'warning'事件名时,处理函数的参数能自动识别为Error类型,不用手动声明。

原实现存在类型推断问题:下面的代码里,调用subscribe处理'b'事件正常,但处理'a'事件时会报错Argument of type '"a"' is not assignable to parameter of type '"b"':

interface Target<N, H> {
  on(name: N, handler: H): unknown;
}

const subscribe = <
  N extends T extends Target<infer N, unknown> ? N : never,
  H extends T extends Target<N, infer H> ? H : never,
  T extends Target<unknown, unknown>,
>(
  name: N,
  handler: H,
  target: T
) => {
  target.on(name, handler);
};

const target: {
  on(name: 'a', handler: (a1: string) => void): void;
  on(name: 'b', handler: (b1: number) => void): void;
} = {
  on: ()=>{},
};

// 报错:类型"a"无法赋值给类型"b"
subscribe('a', (a1) => console.log(a1), target);

// 正常工作
subscribe('b', (b1) => console.log(b1), target); 

问题原因

原Target接口假设事件发射器的on方法只支持单一事件和单一处理函数类型,但实际很多事件发射器(包括示例中的target)的on方法是重载的,能处理多种事件-处理函数组合。原泛型的约束逻辑无法正确解析重载方法的类型关联,导致TypeScript只能推断出最后一个重载的类型(也就是'b'事件对应的类型)。

正确实现

调整泛型定义顺序,配合条件类型提取重载方法中事件名对应的处理函数类型:

// 工具类型:从事件发射器T中,提取事件E对应的处理函数类型
type EventHandler<T, E extends string> = 
  T extends { on(event: E, handler: infer H): any } ? H : never;

const subscribe = <T, E extends string>(
  eventName: E,
  handler: EventHandler<T, E>,
  target: T
) => {
  target.on(eventName, handler);
};

验证效果

用之前的target测试,两个事件都能正确推断类型:

const target: {
  on(name: 'a', handler: (a1: string) => void): void;
  on(name: 'b', handler: (b1: number) => void): void;
} = {
  on: () => {},
};

// a1自动推断为string类型,无报错
subscribe('a', (a1) => console.log(a1), target);

// b1自动推断为number类型,正常工作
subscribe('b', (b1) => console.log(b1), target);

// 测试process的warning事件,warning自动推断为Error类型
subscribe('warning', (warning) => {
  console.log(warning.message);
}, process);

原理说明

  1. 先让TypeScript推断出事件发射器T的完整类型(包括所有重载的on方法);
  2. 再根据传入的eventName推断出具体的事件类型E;
  3. 最后通过EventHandler工具类型,从T的重载on方法中提取对应E的处理函数类型,实现自动关联。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 19:03:22