import { go } from '@blackglory/go' type Listener = (...args: Args) => void export class Emitter< EventToArgs extends Record = Record< string | number | symbol , unknown[] > , Event extends string | number | symbol = keyof EventToArgs > { private map = new Map< Event , Set> >() get [Symbol.toStringTag](): string { return this.constructor.name } on( event: T , listener: Listener ): () => void { const set = go(() => { const set = this.map.get(event) if (set) { return set } else { const set = new Set>() this.map.set(event, set) return set } }) set.add(handler as Listener) return () => { const handlers = this.map.get(event) if (handlers) { const deleted = handlers.delete( handler as Listener ) if (deleted && handlers.size === 0) { this.map.delete(event) } } } function handler(...args: Parameters>): void { listener(...args) } } once( event: T , listener: Listener ): () => void { const removeListener = this.on( event , (...args: Parameters>) => { listener(...args) removeListener() } ) return removeListener } emit(event: T, ...args: EventToArgs[T]): void { this.map.get(event)?.forEach(cb => cb(...args)) } removeAllListeners(event: T): void { this.map.get(event)?.clear() } }