I'm trying to implement simple event dispatcher on TypeScript.
My custom types are declared like this:
events.d.ts:
type AppEvent = { [key: string]: any }
type AppEventListener<T> = <T extends AppEvent>(event: T) => void;
When I pass any object in this function
public addListener<T extends AppEvent>(event: T, listener: AppEventListener<T>)
I get the following error:
Argument of type '(event: TestEvent) => void' is not assignable to parameter of type 'AppEventListener<typeof TestEvent>'.
Types of parameters 'event' and 'event' are incompatible.
Type 'T' is not assignable to type 'TestEvent'.
Property 'name' is missing in type 'AppEvent' but required in type 'TestEvent'.
So, this type AppEvent cannot have any additional properties. How to make it work? Any help appreciated.
Full code example:
class EventDispatcher {
private listeners: Map<AppEvent, Array<AppEventListener<AppEvent>>>
constructor() {
this.listeners = new Map();
}
public dispatch<T extends AppEvent>(event: T): void {
const listeners = this.listeners.get(event.constructor);
if (listeners) {
listeners.forEach((callback) => {
callback(event);
});
}
}
public addListener<T extends AppEvent>(event: T, listener: AppEventListener<T>): void {
let listeners = this.listeners.get(event);
if (!listeners) {
listeners = [listener];
this.listeners.set(event, listeners);
} else {
listeners.push(listener);
}
}
}
class TestEvent {
public name: string = ''
}
const dispatcher = new EventDispatcher();
const listener = (event: TestEvent) => {
console.dir(event);
};
dispatcher.addListener(TestEvent, listener);
const event = new TestEvent('name');
dispatcher.dispatch(event);