export type EventListener = (event: E) => void export class EventEmitter { private readonly events: Map>> = new Map() public addListener(eventName: K, listener: EventListener): void { const eventSet = this.events.get(eventName) if (eventSet === undefined) { this.events.set(eventName, new Set([ listener ]) as Set>) } else { eventSet.add(listener as EventListener) } } public removeListener(eventName: K, listener: EventListener): void { const eventSet = this.events.get(eventName) if (eventSet === undefined) return eventSet.delete(listener as EventListener) if (eventSet.size === 0) { this.events.delete(eventName) } } on = this.addListener off = this.removeListener public emit(eventName: K, event: EventMap[ K ]): void { this.events.get(eventName)?.forEach((listener: EventListener) => { listener.apply(this, [ event ]) }) } }