import { EventEmitter } from 'eventemitter3' type EventMap = Record type EventKey = string & keyof eventMap type EventFn = ( ...parameters: parameters ) => void export type EventData< eventMap extends EventMap, eventName extends keyof eventMap, > = (eventMap[eventName] extends [never] ? unknown : eventMap[eventName]) & { uid: string } export class Emitter { _emitter = new EventEmitter() constructor(public uid: string) {} on>( eventName: key, fn: EventFn< eventMap[key] extends [never] ? [{ uid: string }] : [data: eventMap[key] & { uid: string }] >, ) { this._emitter.on(eventName, fn as EventFn) } once>( eventName: key, fn: EventFn< eventMap[key] extends [never] ? [{ uid: string }] : [data: eventMap[key] & { uid: string }] >, ) { this._emitter.once(eventName, fn as EventFn) } off>( eventName: key, fn: EventFn< eventMap[key] extends [never] ? [{ uid: string }] : [data: eventMap[key] & { uid: string }] >, ) { this._emitter.off(eventName, fn as EventFn) } emit>( eventName: key, ...params: eventMap[key] extends [never] ? [] : [data: eventMap[key]] ) { const data = params[0] this._emitter.emit(eventName, { uid: this.uid, ...data }) } listenerCount>(eventName: key) { return this._emitter.listenerCount(eventName) } } export function createEmitter(uid: string) { return new Emitter(uid) }