Я пытаюсь создать общую систему обработчиков событий, которая обеспечивает безопасное использование типов. Не должно быть возможности подписаться на неправильные типы событий (например, this.on('FooEvent', (event : BarEvent) => ...)
не разрешено).
Вот что у меня есть:
interface Event {
type: string;
}
type EventType<T extends Event> = T['type'];
type EventHandler<T extends Event> = (event: T) => void;
class TypedEventHandler<TEvent extends Event> {
private eventHandlers = new Map<
EventType<TEvent>,
EventHandler<TEvent>[]
>();
on<TOnEvent extends TEvent, TOnType extends TOnEvent['type']>(
type: TOnType,
handler: EventHandler<TOnEvent>,
) {
if (!this.eventHandlers.has(type)) {
this.eventHandlers.set(type, []);
}
this.eventHandlers.get(type)!.push(handler);
}
emit(event: TEvent) {
const handlers = this.eventHandlers.get(event.type);
if (!handlers) return;
handlers.forEach(handler => handler(event));
}
}
К сожалению, .push(handler)
не работает с Argument of type 'EventHandler<TOnEvent>' is not assignable to parameter of type 'EventHandler<TEvent>'
. Можно ли сделать тип переменной eventHandlers
более конкретным, чтобы можно было назначить обработчик?
Я нашел похожие вопросы, подобные этому, однако ни один из них не отвечает на мой вопрос .
TypedEventHandler
:typescript interface MyEventA extends Event { type: 'MyEventA'; } interface MyEventB extends Event { type: 'MyEventB'; foo3: number; } type MyEvent = MyEventA | MyEventB; export default class SomeClass extends TypedEventHandler<MyEvent> { constructor() { super(); this.addEventHandler('MyEventB', this.handler.bind(this)); } handler(event: MyEventB) { // MyEventA is error // ... } doSomething() { this.emit({ type: 'MyEventB', foo3: 42 }); } }
- person Bjarke Walling   schedule 23.11.2019