export type Listener = (event: T) => void export type EventMap = { [K in string]: unknown } export abstract class EventEmitter { private _listeners: { [K in keyof TEventMap]?: [Listener, string | null][] } = {} on( event: TEventType, listener: Listener, key: string | null = null, ): void { this._listeners[event] = [...(this._listeners[event] ?? []), [listener, key]] } off( event: TEventType, listenerOrKey: Listener | string, ): void { this._listeners[event] = (this._listeners[event] ?? []).filter(([listener, key]) => typeof listenerOrKey === "function" ? listener !== listenerOrKey : key !== listenerOrKey, ) } emit( event: TEventType, payload: TEventMap[TEventType], ): void { ;(this._listeners[event] ?? []).forEach((listener) => listener[0](payload)) } }