/* eslint-disable @typescript-eslint/no-explicit-any */ type AnyFunction = (...args: any[]) => any; type EventMap = Record; export class EventTarget { private readonly _listeners = new Map>(); public addEventListener(event: K, cb: Events[K]): this { const set = this._listeners.get(event) || new Set(); this._listeners.set(event, set); set.add(cb as AnyFunction); return this; } public removeEventListener(event: K, cb: Events[K]): this { this._listeners.get(event)?.delete(cb as AnyFunction); return this; } public dispatchEvent(event: K, ...data: Parameters): unknown { let ok = true; for (const cb of (this._listeners.get(event) || [])) { ok = (cb(...data) !== false) && ok; } return ok; } public unbindAllListeners(): void { this._listeners.clear(); } // Let's also support on, off and emit like node /* eslint-disable no-invalid-this */ public on = this.addEventListener; public off = this.removeEventListener; public emit = this.dispatchEvent; }