前置知识: TypeScript

类型安全的发布订阅

1 minIntermediate2026/6/14

构建类型安全的发布订阅模式

1. 型定义

type EventMap = {
  'user:login': { userId: string; timestamp: Date };
  'user:logout': { userId: string };
  'cart:add': { productId: string; quantity: number };
  'cart:remove': { productId: string };
  'order:create': { orderId: string; total: number };
};

type EventKey = keyof EventMap;
type EventHandler<K extends EventKey> = (payload: EventMap[K]) => void;

2. 实现

class PubSub<Events extends Record<string, any>> {
  private subscribers = new Map<keyof Events, Set<Function>>();

  subscribe<K extends keyof Events & string>(
    event: K,
    handler: (payload: Events[K]) => void
  ): () => void {
    if (!this.subscribers.has(event)) {
      this.subscribers.set(event, new Set());
    }
    this.subscribers.get(event)!.add(handler);
    return () => this.subscribers.get(event)?.delete(handler);
  }

  publish<K extends keyof Events & string>(event: K, payload: Events[K]): void {
    this.subscribers.get(event)?.forEach((fn) => fn(payload));
  }

  once<K extends keyof Events & string>(
    event: K,
    handler: (payload: Events[K]) => void
  ): () => void {
    const unsubscribe = this.subscribe(event, (payload) => {
      handler(payload);
      unsubscribe();
    });
    return unsubscribe;
  }
}

const bus = new PubSub<EventMap>();
bus.subscribe('user:login', ({ userId }) => console.log(userId));
bus.publish('user:login', { userId: '123', timestamp: new Date() });