observer.ts
typescript/patterns/observer.ts
TypeScript
Observer / EventEmitter pattern with typed events and automatic cleanup.
observer.ts
/**
* @description Observer / EventEmitter pattern with typed events and automatic cleanup.
* @tags pattern, events, observer, pub-sub
*/
type Listener<T> = (event: T) => void;
type UnsubscribeFn = () => void;
export class EventBus<Events extends Record<string, unknown>> {
private listeners = new Map<keyof Events, Set<Listener<unknown>>>();
on<K extends keyof Events>(event: K, listener: Listener<Events[K]>): UnsubscribeFn {
if (!this.listeners.has(event)) {
this.listeners.set(event, new Set());
}
const set = this.listeners.get(event)!;
set.add(listener as Listener<unknown>);
return () => {
set.delete(listener as Listener<unknown>);
if (set.size === 0) this.listeners.delete(event);
};
}
emit<K extends keyof Events>(event: K, data: Events[K]): void {
const set = this.listeners.get(event);
if (!set) return;
for (const listener of set) {
listener(data);
}
}
clear(): void {
this.listeners.clear();
}
}