Code
type EventMap = Record<string, any>;type EventKey<T extends EventMap> = string & keyof T;type EventReceiver<T> = (params: T) => void;interface Emitter<T extends EventMap> { on<K extends EventKey<T>>(eventName: K, fn: EventReceiver<T[K]>): void; off<K extends EventKey<T>>(eventName: K, fn: EventReceiver<T[K]>): void; emit<K extends EventKey<T>>(eventName: K, data: T[K]): void; once<K extends EventKey<T>>(eventName: K, fn: EventReceiver<T[K]>): void;}class EventEmitter<T extends EventMap> implements Emitter<T> { private listeners: { [K in keyof T]?: Array<EventReceiver<T[K]>>; } = {}; on<K extends EventKey<T>>(eventName: K, fn: EventReceiver<T[K]>): void { if (!this.listeners[eventName]) { this.listeners[eventName] = []; } this.listeners[eventName]!.push(fn); } off<K extends EventKey<T>>(eventName: K, fn: EventReceiver<T[K]>): void { const handlers = this.listeners[eventName]; if (handlers) { this.listeners[eventName] = handlers.filter(f => f !== fn); } } emit<K extends EventKey<T>>(eventName: K, data: T[K]): void { const handlers = this.listeners[eventName]; if (handlers) { handlers.forEach(fn => fn(data)); } } once<K extends EventKey<T>>(eventName: K, fn: EventReceiver<T[K]>): void { const onceWrapper = ((data: T[K]) => { fn(data); this.off(eventName, onceWrapper); }) as EventReceiver<T[K]>; this.on(eventName, onceWrapper); }}export default EventEmitter;import EventEmitter from './EventEmitter';interface MyEvents { 'user:login': { userId: string; email: string }; 'user:logout': { userId: string }; 'message:send': { text: string; timestamp: number };}const emitter = new EventEmitter<MyEvents>();emitter.on('user:login', (data) => { console.log(`User ${data.userId} logged in with email ${data.email}`);});emitter.once('user:logout', (data) => { console.log(`User ${data.userId} logged out`);});emitter.emit('user:login', { userId: 'user123', email: '[email protected]' });emitter.emit('message:send', { text: 'Hello, world!', timestamp: Date.now() });
Comments
No comments yet. Be the first!
Please login to leave a comment.