export type Listener = (...args: any[]) => any; export type TypedEvents = {[k in string | symbol]: Listener} & {'*': (event: string, ...args: any[]) => any}; export class TypedEmitter { private listeners: { [key in keyof T]?: Function[] } = {}; emit(event: K, ...args: Parameters) { (this.listeners['*'] || []).forEach(l => l(event, ...args)); (this.listeners[event] || []).forEach(l => l(...args)); }; off(event: K, listener: T[K]): this { console.log('cleared'); this.listeners[event] = (this.listeners[event] || []).filter(l => l === listener); return this; } on(event: K, listener: T[K]) { if(!this.listeners[event]) this.listeners[event] = []; this.listeners[event]?.push(listener); return () => this.off(event, listener); } once(event: K, listener?: T[K]): Promise { return new Promise(res => { const unsubscribe = this.on(event, ((...args: any) => { res(args.length == 1 ? args[0] : args); if(listener) listener(...args); unsubscribe(); })); }); } }