I'm trying to take the following code for an event dispatcher, and make the types used (classes and interfaces) more specified.
- Note that I'm generally interested in understanding why my usage here with types/classes/interfaces/generic types here doesn't work, and less interested in events per se.
type Handler<E> = (event: E) => void;
class EventDispatcher<E> {
private handlers: Handler<E>[] = [];
fire(event: E) {
for (let h of this.handlers)
h(event);
}
register(handler: Handler<E>) {
this.handlers.push(handler);
}
}
What I'd like to achieve:
Use Typescript's
CustomEvent<any>instead ofE.Be able to define specific custom events that
extendsCustomEvent<any>, for example:export class FormClearedEvent extends CustomEvent<any> { constructor() { super("formCleared"); } }Export those specific custom event, together with the handler and the event dispacther
First attempt, doesn't compile:
export type Handler<CustomEvent<any>> = (event: CustomEvent<any>) => void; // <-- doesn't compile
// Also, using CustomEvent<any> as the type parameter for the dispacther and its methods, doesn't compile as well.
Second attempt, makes me duplicate SpecificEvent extends CustomEvent<any>> all over the place, and doesn't compile:
export type Handler<SpecificEvent extends CustomEvent<any>> = (event: SpecificEvent) => void;
export class EventDispatcher<SpecificEvent extends CustomEvent<any>> {
private handlers: Handler<SpecificEvent extends CustomEvent<any>>[] = []; // <-- doesn't compile
fire(event: SpecificEvent extends CustomEvent<any>) { // <-- doesn't compile
for (let handler of this.handlers) {
handler(event);
}
}
register(handler: Handler<SpecificEvent extends CustomEvent<any>>) { // <-- doesn't compile
this.handlers.push(handler);
}
}
// specific events
export class FormClearedEvent extends CustomEvent<any> {
constructor() {
super("formCleared");
}
}
Third attempt, works, but now I have two classes which are really the same one (CustomEvent<any> and SpecificEvent):
// specific events
class SpecificEvent extends CustomEvent<any> { }
export class FormClearedEvent extends CustomEvent<any> {
constructor() {
super("formCleared");
}
}
// SpecificEvent handler
export type Handler<SpecificEvent> = (event: SpecificEvent) => void;
// SpecificEvent dispatcher
export class EventDispatcher<SpecificEvent> {
private handlers: Handler<SpecificEvent>[] = [];
fire(event: SpecificEvent) {
for (let handler of this.handlers) {
handler(event);
}
}
register(handler: Handler<SpecificEvent>) {
this.handlers.push(handler);
}
}
My Question:
- Why my first attempt doesn't compile?
- Why some of the code in my second attempt doesn't compile?
- Can I do better than the third way?