export interface EventDefinitions { [key: string]: EventListener; } export type EventKeys = (keyof T) & ({ [key in keyof T]: string extends key ? never : number extends key ? never : key; } extends { [_ in keyof T]: infer U } ? U : never); export type EventListener = (...args: any[]) => void; export interface IEventSource { on>(event: T, listener: TEvents[T]): void; off>(event: T, listener: TEvents[T]): void; } export class EventEmitter implements IEventSource { listeners = new Map(); on(event: T, listener: TEvents[T]) { if (!this.listeners.has(event)) this.listeners.set(event, []); this.listeners.get(event)?.push(listener); } off(event: T, listener: TEvents[T]) { if (this.listeners.has(event)) this.listeners.set(event, this.listeners.get(event)?.filter(f => f !== listener) ?? []); } emit(event: T, ...args: Parameters) { this.listeners.get(event)?.forEach(f => f(...args)); } }