type EventArgs = T extends any[] ? T : T extends any ? [T] : never[] type EventReceiver = (...args: EventArgs) => void interface EventMap { [event: string]: any } export class Emitter { private callbacks: { [E in keyof M]?: Array> } = {} on(event: E, callback: EventReceiver): this { if (!this.callbacks[event]) { this.callbacks[event] = [] } this.callbacks[event]!.push(callback) return this } once(event: E, fn: EventReceiver): this { const on = (...args: EventArgs): void => { this.off(event, on) fn.apply(this, args) } this.on(event, on) return this } off(event: E, callback: EventReceiver): this { const fns = this.callbacks[event] if (fns) { const without = fns.filter((fn) => fn !== callback) this.callbacks[event] = without } return this } emit(event: E, ...args: EventArgs): this { const fns = this.callbacks[event] if (fns) { fns.forEach((fn) => fn.apply(this, args)) } return this } removeListeners() { this.callbacks = {} } }