ts-04-event-emitter
1.000
Proposed solution
```typescript
export class EventEmitter<Events extends Record<string, unknown[]>> {
private listeners: Map<keyof Events, Array<(...args: any[]) => void>> = new Map();
on<E extends keyof Events>(event: E, fn: (...args: Events[E]) => void): () => void {
if (!this.listeners.has(event)) {
this.listeners.set(event, []);
}
const eventListeners = this.listeners.get(event)!;
eventListeners.push(fn);
return () => {
const index = eventListeners.indexOf(fn);
if (index !== -1) {
eventListeners.splice(index, 1);
}
};
}
off<E extends keyof Events>(event: E, fn: (...args: Events[E]) => void): void {
if (!this.listeners.has(event)) {
return;
}
const eventListeners = this.listeners.get(event)!;
const index = eventListeners.indexOf(fn);
if (index !== -1) {
eventListeners.splice(index, 1);
}
}
emit<E extends keyof Events>(event: E, ...args: Events[E]): void {
if (!this.listeners.has(event)) {
return;
}
const eventListeners = this.listeners.get(event)!;
for (const listener of eventListeners) {
listener(...args);
}
}
}
```Test output (stdout)
TAP version 13 # Subtest: calls a registered listener with args ok 1 - calls a registered listener with args --- duration_ms: 1.060626 type: 'test' ... # Subtest: multiple listeners fire in registration order ok 2 - multiple listeners fire in registration order --- duration_ms: 0.081161 type: 'test' ... # Subtest: passes multiple typed args ok 3 - passes multiple typed args --- duration_ms: 0.05468 type: 'test' ... # Subtest: returned unsubscribe removes the listener ok 4 - returned unsubscribe removes the listener --- duration_ms: 0.05146 type: 'test' ... # Subtest: off removes a specific listener, leaving others ok 5 - off removes a specific listener, leaving others --- duration_ms: 0.076051 type: 'test' ... # Subtest: emitting an event with no listeners is a no-op ok 6 - emitting an event with no listeners is a no-op --- duration_ms: 0.07677 type: 'test' ... # Subtest: off on an unregistered listener is a no-op ok 7 - off on an unregistered listener is a no-op --- duration_ms: 0.04146 type: 'test' ... # Subtest: the same function registered twice fires twice ok 8 - the same function registered twice fires twice --- duration_ms: 0.06751 type: 'test' ... 1..8 # tests 8 # suites 0 # pass 8 # fail 0 # cancelled 0 # skipped 0 # todo 0 # duration_ms 80.553033
System prompt
You are an expert programmer. Solve the task exactly as specified. Output your solution as fenced code blocks using the required file name(s) and the exact function/type signatures requested. Prefer correctness; do not include prose outside code unless asked.