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

如何在TypeScript中基于动态事件注册表自动推断Handler参数类型?

动态注册事件的TypeScript自动类型推断方案

需求是开发TypeScript应用时,事件及其参数通过registerEvent动态注册,on方法要能自动根据注册信息推断参数类型,无需手动编写方法重载。

原实现的问题

原代码中Test类的泛型RE被定义为单一的ParameterSchema,无法存储多个不同事件的参数结构,导致on方法无法关联到具体事件的注册信息,类型推断失效。

解决方案

调整泛型设计,让Test类的泛型跟踪所有已注册的事件集合,利用TypeScript的条件类型和泛型推断实现自动类型关联:

type ParameterType<T> = {
  regexSnippet: string,
  parse?: (value: string) => any,
  type: T
}

const ParameterTypes = {
  "string": { regexSnippet: "\\w+" } as ParameterType<string>,
  "string?": { regexSnippet: "\\w*" } as ParameterType<string | undefined>,
  "number": { regexSnippet: "\\d+", parse: parseInt } as ParameterType<number>,
  "number?": { regexSnippet: "\\d*", parse: parseInt } as ParameterType<number | undefined>,
} as const

type ParameterTypesMap = typeof ParameterTypes
type ParameterTypeKeys = keyof ParameterTypesMap
type ParameterSchema = { [name: string]: ParameterTypeKeys }

// 泛型改为跟踪所有已注册的事件集合
class Test<Events extends Record<string, ParameterSchema> = {}> {
  private registeredEvents: Events = {} as Events;

  // 扩展泛型,返回更新后的实例类型
  registerEvent<EvName extends string, EvSchema extends ParameterSchema>(
    evname: EvName,
    args: EvSchema
  ): Test<Events & Record<EvName, EvSchema>> {
    (this.registeredEvents as any)[evname] = args;
    return this as Test<Events & Record<EvName, EvSchema>>;
  }

  // 基于泛型Events自动推断参数类型
  on<EvName extends keyof Events>(
    evname: EvName,
    args: { 
      [K in keyof Events[EvName]]: ParameterTypesMap[Events[EvName][K]]["type"] 
    }
  ): void {
    // 业务逻辑实现
  }
}

// 链式调用或分步调用,让TypeScript跟踪泛型变化
const test = new Test()
  .registerEvent("a", { name: "string", age: "number" })
  .registerEvent("b", { nickname: "string?" })
  .registerEvent("c", { count: "number" });

// 类型校验正常工作
test.on("c", { count: 12 }); // ✅ 正确
test.on("c", { zzzzz: 12 }); // ❌ 类型错误:不存在zzzzz属性
test.on("b", { nickname: "test" }); // ✅ 正确
test.on("b", { nickname: undefined }); // ✅ 正确
test.on("a", { name: "Alice", age: 30 }); // ✅ 正确
test.on("a", { name: "Alice", age: "30" }); // ❌ 类型错误:age应为number

关键说明

  • 泛型跟踪事件集合:Test类的泛型Events默认是空对象,每次调用registerEvent时,通过Events & Record<EvName, EvSchema>扩展泛型,记录新注册的事件及其参数结构。
  • registerEvent的返回类型:返回Test<Events & Record<EvName, EvSchema>>,让TypeScript能在链式调用时更新实例的泛型类型,分步调用时也能正确推断。
  • on方法的类型推断:通过EvName extends keyof Events限定事件名,再用映射类型将事件的参数schema转换为实际的类型,实现与注册内容的强关联。

这样就完全满足约束条件:无需硬编码,on方法的类型校验完全与registerEvent的注册内容关联,动态生成类型校验规则。

内容的提问来源于stack exchange,提问作者Daniel de Andrade Varela

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 11:21:10