TypeScript通用事件回调类型疑问:为何参数被转为联合类型?
解决TypeScript通用事件处理器的联合类型推断问题
问题根源
你遇到的类型错误,是因为将泛型类型OnEvent、TriggerEvent直接赋值给类成员方法时,TypeScript无法保留泛型的具体约束,会把泛型参数T解析为所有EventName的联合类型。这导致callback被推断为FooCallback | BarCallback,args被推断为{ foo: string } | { bar: number }。而this.events[eventName]此时的类型是FooCallback[] | BarCallback[],TypeScript会要求push的参数必须同时满足两种回调类型的交集(因为它无法确定当前操作的是哪个数组),最终引发类型不匹配的报错。
修复方案
不要通过类型别名给类成员赋值泛型函数类型,而是直接在类的方法上定义泛型参数。这样每次调用on或trigger时,TypeScript会根据传入的eventName自动推断出具体的T,确保回调和参数类型与事件严格对应:
type FooCallback = (props: { foo: string }) => void type BarCallback = (props: { bar: number }) => void type Events = { "foo": FooCallback[], "bar": BarCallback[] } type EventName = keyof Events export default class Broadcast { private events: Events = { foo: [], bar: [] } constructor() {} on<T extends EventName>(eventName: T, callback: Events[T][number]): void { this.events[eventName].push(callback) } trigger<T extends EventName>(eventName: T, args: Parameters<Events[T][number]>[0]): void { this.events[eventName].forEach(callback => { callback(args) }) } }
修复说明
- 将泛型参数
T的定义从类型别名移到类方法上,让TypeScript在每次方法调用时都能精准推断T的具体值,避免泛型被擦除为联合类型。 - 直接在方法上声明参数和返回值类型,确保类型检查的准确性,同时保持代码的可读性。
内容的提问来源于stack exchange,提问作者Sean
相关产品推荐
相关产品推荐

