// type EventCallback = (...args: any[]) => void; // export class myEventEmitter { // private events: Map>; // constructor() { // this.events = new Map(); // } // public on(eventName: string, callback: EventCallback) { // if (!this.events.has(eventName)) { // this.events.set(eventName, new Set()); // } // const eventListeners = this.events.get(eventName); // eventListeners.add(callback); // } // public once(eventName: string, callback: EventCallback) { // const onceCallback: EventCallback = (...args: any[]) => { // this.off(eventName, onceCallback); // callback(...args); // }; // this.on(eventName, onceCallback); // } // public off(eventName: string, callback: EventCallback) { // if (!this.events.has(eventName)) { // return; // } // const eventListeners = this.events.get(eventName); // let isSucc = eventListeners.delete(callback); // if (eventListeners.size === 0) { // this.events.delete(eventName); // } // } // public emit(eventName: string, ...args: any[]) { // if (!this.events.has(eventName)) { // return; // } // const eventListeners = this.events.get(eventName); // eventListeners.forEach((callback) => { // callback(...args); // }); // } // } type Listener = (...args: T) => void; interface EventMap { [event: string]: unknown[]; } interface ListenerMap { [event: string]: Listener[]; } interface EventEmitter { on(event: string, listener: Listener): this; once(event: string, listener: Listener): this; off(event: string, listener: Listener): this; emit(event: string, ...args: T): this; } class EventEmitterImpl implements EventEmitter { private events: EventMap = {}; private listeners: ListenerMap = {}; public on(event: string, listener: Listener): this { this.addListener(event, listener); return this; } public once(event: string, listener: Listener): this { const onceListener: Listener = (...args: T) => { this.off(event, onceListener); listener(...args); }; this.addListener(event, onceListener); return this; } public off(event: string, listener: Listener): this { const listeners = this.listeners[event]; if (!listeners) return this; const index = listeners.indexOf(listener); if (index >= 0) { listeners.splice(index, 1); if (listeners.length === 0) { delete this.events[event]; delete this.listeners[event]; } } return this; } public emit(event: string, ...args: T): this { const listeners = this.listeners[event]; if (!listeners) return this; const events = this.events[event] as T; if (events) { events.push(...args); } else { this.events[event] = args; } listeners.slice().forEach((listener) => listener(...args)); return this; } public clear(): void { this.events = {}; this.listeners = {}; } private addListener(event: string, listener: Listener): void { if (!this.listeners[event]) { this.listeners[event] = []; } this.listeners[event].push(listener); } } export const myEventEmitter = EventEmitterImpl;