import { pushUnique, removeItem } from "./collection"; export type EventMap = Record | never; export type DefaultEventMap = [never]; export type AnyRest = [...args: any[]]; export type Args = T extends DefaultEventMap ? AnyRest : K extends keyof T ? T[K] : never; export type Key = T extends DefaultEventMap ? number : K | keyof T; export type Listener = T extends DefaultEventMap ? F : K extends keyof T ? T[K] extends unknown[] ? (...args: T[K]) => void : never : never; export type Listener1 = Listener void>; export class BasicEventEmitter> { private listeners = new Map>, any>(); on(eventName: Key, listener: Listener1): () => void { const arr = this.listeners.get(eventName) || []; pushUnique(arr, listener); this.listeners.set(eventName, arr); return () => { this.off(eventName, listener); }; } off(eventName: Key, listener: Listener1): boolean { const arr = this.listeners.get(eventName) || []; removeItem(arr, listener); if (!arr.length) { this.listeners.delete(eventName); return true; } return false; } emit(eventName: Key, ...args: Args): Promise { const listeners = this.listeners.get(eventName); const promises: Promise[] = []; if (listeners) { for (let i = 0; i < listeners.length; i++) { try { const listener = listeners[i]; if (listener) { const result = listener(...args); if (result instanceof Promise) { promises.push(result); } } } catch (error) { console.error(error); } } } return Promise.all(promises); } listenersCount(type: Key) { const arr = this.listeners.get(type); return arr ? arr.length : 0; } removeAllListeners() { this.listeners.clear(); } removeSpecificListeners(type: Key) { this.listeners.delete(type); } }