typescriptintermediate

Event-Driven Architecture Pattern

Build loosely coupled systems with typed event bus, async event handlers, and domain event patterns.

typescript
import { EventEmitter } from 'events';

// Typed event system
type EventMap = {
  'user:created': { id: string; email: string; name: string };
  'user:updated': { id: string; changes: Record<string, unknown> };
  'user:deleted': { id: string };
  'order:placed': { orderId: string; userId: string; total: number };
  'email:send': { to: string; subject: string; body: string };
};

class TypedEventBus {
  private emitter = new EventEmitter();

  on<K extends keyof EventMap>(event: K, handler: (data: EventMap[K]) => void | Promise<void>) {
    this.emitter.on(event, handler);
    return this;
  }

  emit<K extends keyof EventMap>(event: K, data: EventMap[K]) {
    this.emitter.emit(event, data);
  }

  once<K extends keyof EventMap>(event: K, handler: (data: EventMap[K]) => void) {
    this.emitter.once(event, handler);
    return this;
  }

  off<K extends keyof EventMap>(event: K, handler: (data: EventMap[K]) => void) {
    this.emitter.off(event, handler);
  }
}

// Singleton bus
const bus = new TypedEventBus();

// Handlers (separate modules in real app)
bus.on('user:created', async (data) => {
  console.log(`[DB] Saving user: ${data.name}`);
});

bus.on('user:created', async (data) => {
  bus.emit('email:send', {
    to: data.email,
    subject: 'Welcome!',
    body: `Hi ${data.name}, welcome aboard!`,
  });
});

bus.on('order:placed', async (data) => {
  console.log(`[Inventory] Processing order ${data.orderId}`);
  console.log(`[Analytics] Order $${data.total} by ${data.userId}`);
});

bus.on('email:send', async (data) => {
  console.log(`[Email] To: ${data.to} | Subject: ${data.subject}`);
});

// Emit events
bus.emit('user:created', { id: 'u1', email: 'alice@test.com', name: 'Alice' });
bus.emit('order:placed', { orderId: 'ord-1', userId: 'u1', total: 99.99 });

Use Cases

  • Microservice communication
  • Decoupled module architecture
  • Domain event processing

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.