Senior LevelJavaScript & TypeScript
How to build a custom type-safe Event Emitter / PubSub system in TypeScript?
❓ Interview Prompt: Explain strongly typed event names, payload mapping generics, listener subscriptions, and unbind functions.
A standard EventEmitter accepts any string and untyped payloads. A Type-Safe EventEmitter enforces that event names and their corresponding payload types are strictly validated at compile time.
Design Approach:
Accept a generic event map interface EventMap where keys are event names and values are callback payload types. Map listener methods (on, emit, off) against keyof EventMap.
Code Implementation Example
typescript
type EventMap = {
'user:login': { userId: string; timestamp: number };
'cart:update': { itemCount: number; total: number };
};
class TypedEventEmitter<T extends Record<string, any>> {
private listeners: { [K in keyof T]?: ((data: T[K]) => void)[] } = {};
on<K extends keyof T>(event: K, fn: (data: T[K]) => void): () => void {
if (!this.listeners[event]) this.listeners[event] = [];
this.listeners[event]!.push(fn);
return () => {
this.listeners[event] = this.listeners[event]!.filter(l => l !== fn);
};
}
emit<K extends keyof T>(event: K, data: T[K]): void {
this.listeners[event]?.forEach(fn => fn(data));
}
}
const emitter = new TypedEventEmitter<EventMap>();
emitter.on('user:login', (data) => {
console.log(data.userId.toUpperCase()); // ✅ TS knows data.userId is string!
});
emitter.emit('user:login', { userId: 'u123', timestamp: Date.now() });💡Type-safe event emitter mapping event names directly to callback payloads.
🎯 Interview Key Takeaway
Use generic EventMap interfaces to constrain event names and payload parameters across EventEmitter systems.
#TypeScript#EventEmitter#PubSub#Senior
Back to all JavaScript & TypeScript Questions→