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

TypeScript中如何为枚举事件绑定对应类型的处理函数签名

实现方案

你可以通过泛型+事件签名映射的方式实现需求,不需要额外声明运行时变量,所有关联逻辑仅在类型层面生效,无额外运行时开销。

方案1:泛型映射类型(更易维护,推荐)

步骤1:定义事件与处理函数的映射关系

首先声明一个接口,将每个枚举值对应的处理函数签名一一关联,这一步是纯类型定义,不会生成任何运行时代码,也不需要额外赋值:

enum Event {
  EventOne,
  EventTwo
}

// 事件与处理函数的签名映射,仅用于类型校验
interface EventHandlerMap {
  [Event.EventOne]: (foo: number, bar: string) => void
  [Event.EventTwo]: (foo: string) => void
}

步骤2:改造registerEvent为泛型函数

给函数添加约束为Event枚举的泛型参数,将第二个入参的类型绑定为映射中对应泛型的签名:

function registerEvent<T extends Event>(event: T, handler: EventHandlerMap[T]) {
  // 此处保留你原有的事件注册逻辑即可
}

效果验证

调用时TS会自动根据传入的事件枚举值推断对应处理函数的签名,支持智能提示,类型不匹配会直接报错:

// 正常匹配:EventOne对应的处理函数参数自动推断为number、string
registerEvent(Event.EventOne, (foo, bar) => {
  console.log(foo.toFixed(2), bar.length) // 参数属性有智能提示
})

// 正常匹配:EventTwo对应的处理函数参数自动推断为string
registerEvent(Event.EventTwo, (foo) => {
  console.log(foo.length)
})

// 类型报错:EventOne的处理函数第二个参数应为string,此处声明为boolean不符合要求
registerEvent(Event.EventOne, (foo: number, bar: boolean) => {})

后续新增事件只需要在Event枚举加值,同时在EventHandlerMap中补充对应签名即可,不需要修改registerEvent的代码,维护成本极低。

方案2:函数重载(适合事件数量少的场景)

如果事件数量很少,也可以直接通过函数重载实现,不需要额外定义映射接口:

enum Event {
  EventOne,
  EventTwo
}

// 重载签名:逐个声明每个事件对应的处理函数类型
function registerEvent(event: Event.EventOne, handler: (foo: number, bar: string) => void): void
function registerEvent(event: Event.EventTwo, handler: (foo: string) => void): void

// 实现签名:仅对内生效,对外不会暴露
function registerEvent(event: Event, handler: (...args: any[]) => void) {
  // 原有事件注册逻辑
}

效果和方案1完全一致,缺点是新增事件时需要额外加重载签名,事件多了之后会比较冗余。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 10:54:03