type Listener = (payload: TPayload) => void; type ListenerMap> = { [TKey in keyof TEvents]?: Set>; }; function getListeners< TEvents extends Record, TKey extends keyof TEvents, >( map: ListenerMap, key: TKey, ): Set> | undefined { return map[key] as Set> | undefined; } export class EventEmitter> { private readonly listeners: ListenerMap = {}; on( event: TKey, listener: Listener, ): () => void { const existing = getListeners(this.listeners, event); if (existing) { existing.add(listener); } else { this.listeners[event] = new Set([listener]) as ListenerMap[TKey]; } return () => { this.off(event, listener); }; } off( event: TKey, listener: Listener, ): void { const currentListeners = getListeners(this.listeners, event); if (!currentListeners) { return; } currentListeners.delete(listener); if (currentListeners.size === 0) { delete this.listeners[event]; } } emit(event: TKey, payload: TEvents[TKey]): void { const currentListeners = getListeners(this.listeners, event); if (!currentListeners) { return; } currentListeners.forEach((listener) => { listener(payload); }); } clear(): void { for (const key of Object.keys(this.listeners) as (keyof TEvents)[]) { delete this.listeners[key]; } } }