typescriptadvanced
Typed Event Emitter Class
Build a type-safe event emitter with TypeScript generics for strongly-typed event handling.
typescriptPress ⌘/Ctrl + Shift + C to copy
import { EventEmitter } from 'events';
// Type-safe event emitter wrapper
class TypedEmitter<Events extends Record<string, any[]>> {
private emitter = new EventEmitter();
on<K extends keyof Events & string>(
event: K,
listener: (...args: Events[K]) => void
): this {
this.emitter.on(event, listener as any);
return this;
}
once<K extends keyof Events & string>(
event: K,
listener: (...args: Events[K]) => void
): this {
this.emitter.once(event, listener as any);
return this;
}
emit<K extends keyof Events & string>(
event: K,
...args: Events[K]
): boolean {
return this.emitter.emit(event, ...args);
}
off<K extends keyof Events & string>(
event: K,
listener: (...args: Events[K]) => void
): this {
this.emitter.off(event, listener as any);
return this;
}
removeAllListeners<K extends keyof Events & string>(event?: K): this {
this.emitter.removeAllListeners(event);
return this;
}
listenerCount<K extends keyof Events & string>(event: K): number {
return this.emitter.listenerCount(event);
}
}
// Define event types
type ServerEvents = {
connection: [clientId: string, address: string];
message: [clientId: string, data: Buffer];
disconnect: [clientId: string, reason: string];
error: [error: Error];
};
// Use typed emitter
const server = new TypedEmitter<ServerEvents>();
server.on('connection', (clientId, address) => {
// TypeScript knows: clientId is string, address is string
console.log(`Connected: ${clientId} from ${address}`);
});
server.on('message', (clientId, data) => {
// TypeScript knows: data is Buffer
console.log(`Message from ${clientId}: ${data.toString()}`);
});
server.on('disconnect', (clientId, reason) => {
console.log(`Disconnected: ${clientId} (${reason})`);
});
server.on('error', (error) => {
console.error('Error:', error.message);
});
// Emit events (type-checked!)
server.emit('connection', 'client-1', '192.168.1.1');
server.emit('message', 'client-1', Buffer.from('hello'));
server.emit('disconnect', 'client-1', 'timeout');
// This would cause a TypeScript error:
// server.emit('connection', 123); // Error: number not assignable to string
// server.emit('unknown', 'data'); // Error: 'unknown' not in ServerEvents
// Application-level events
type AppEvents = {
'user:created': [user: { id: string; email: string }];
'user:deleted': [userId: string];
'order:placed': [orderId: string, total: number];
'cache:invalidated': [keys: string[]];
};
const app = new TypedEmitter<AppEvents>();
app.on('user:created', (user) => {
console.log(`New user: ${user.email}`);
});
app.on('order:placed', (orderId, total) => {
console.log(`Order ${orderId}: $${total}`);
});
app.emit('user:created', { id: '1', email: 'alice@test.com' });
app.emit('order:placed', 'ord-123', 99.99);
console.log('\nListeners:', app.listenerCount('user:created'));Use Cases
- Type-safe event-driven architecture
- Application event bus
- Domain event handling
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
typescriptintermediate
TypeScript Typed Event Emitter
Create type-safe event emitters in Node.js with full TypeScript support and autocomplete.
Best for: Type-safe pub/sub communication between modules
#nodejs#events
typescriptintermediate
Request Validation Schema Builder
Build a lightweight request validation layer with type inference for API endpoints.
Best for: API request body validation
#nodejs#validation
typescriptbeginner
Custom Error Classes
Create typed custom error classes with HTTP status codes, error codes, and structured error handling.
Best for: Structured API error responses
#nodejs#error
typescriptintermediate
Event-Driven Architecture Pattern
Build loosely coupled systems with typed event bus, async event handlers, and domain event patterns.
Best for: Microservice communication
#nodejs#events