/** * Allowed event name. */ type EventName = string | number | symbol; type EventHandler = (value?: Value) => any; /** * An internally used event emitter model. */ class EventEmitter = {}> { private eventMap = new Map>; /** * Add a listener for a given event. * @param event - event name. * @param handler - event handler. */ public addListener(event: T, handler: EventHandler): void { let handlerSet = this.eventMap.get(event); if (!handlerSet) { handlerSet = new Set(); this.eventMap.set(event, handlerSet); } handlerSet.add(handler); } /** * Alias of `EventEmitter.addListener`. */ public declare on: (event: T, handler: EventHandler) => void; /** * Remove the listeners of a given event. * @param event - event name. * @param handler - event handler. */ public removeListener(event: T, handler: EventHandler) { let handlerSet = this.eventMap.get(event); if (handlerSet) { handlerSet.delete(handler); } } /** * Alias of `EventEmitter.removeListener`. */ public declare off: (event: T, handler: EventHandler) => void; /** * Remove all listeners of a given event. * @param event - event name. * @param handler - event handler. */ public removeAllListener(event: T) { this.eventMap.set(event, new Set()); } /** * Alias of `EventEmitter.removeAllListener`. */ public declare offAll: (event: T) => void; /** * emit event. */ public emit(...param: EventMap[T] extends void ? [T] : [T, EventMap[T]]) { let handlerSet = this.eventMap.get(param[0]); if (handlerSet) { for (const handler of handlerSet) { handler(param[1]); } } } /** * Remove all listeners. */ public clearAllListener() { this.eventMap.clear(); this.eventMap = new Map(); } /** * Get the number of listeners for a given event. * @param event - event name. */ public listenerCount(event: T): number { let handlerSet = this.eventMap.get(event); if (handlerSet) { return handlerSet.size; } else { return 0; } } } // Register alias. EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.off = EventEmitter.prototype.removeListener; EventEmitter.prototype.offAll = EventEmitter.prototype.removeAllListener; export { EventEmitter };