基于函数参数中的另一个参数从 type-map 强制转换类型

Cast type from type-map based on another parameter in function arguments

提问人:Sourabh 提问时间:10/20/2023 更新时间:10/20/2023 访问量:16

问:

我正在用打字稿编写一个事件总线:

export type Subscriber<ET, P> = (type: ET, payload: P) => void;

export class EventBus<
  EventType extends string,
  PayloadMap extends Record<EventType, any> = Record<EventType, any>
> {
  private subscribers: Map<
    EventType,
    Set<Subscriber<EventType, PayloadMap[EventType]>>
  > = new Map();
  private stickyEvents: Map<EventType, PayloadMap[EventType][]> = new Map();

  private validInput = (
    type: EventType,
    callback: Subscriber<EventType, PayloadMap[EventType]>
  ) =>
    !!type &&
    typeof type === "string" &&
    type.length > 0 &&
    !!callback &&
    typeof callback === "function";

  public subscribe(
    type: EventType,
    callback: Subscriber<EventType, PayloadMap[EventType]>
  ) {
    if (!this.validInput(type, callback)) return;

    const callbacks = this.subscribers.get(type) || new Set();
    callbacks.add(callback);
    this.subscribers.set(type, callbacks);

    const stickies = this.stickyEvents.get(type) || [];
    if (stickies.length > 0) {
      stickies.forEach((event) => {
        callbacks.forEach((cb) => cb(type, event));
      });
      this.stickyEvents.set(type, []);
    }
  }

  public unsubscribe(
    type: EventType,
    callback: Subscriber<EventType, PayloadMap[EventType]>
  ) {
    if (!this.validInput(type, callback)) return;
    const callbacks = this.subscribers.get(type);
    if (callbacks) {
      callbacks.delete(callback);
    }
  }

  public publish(type: EventType, payload: PayloadMap[EventType]) {
    const eventSubscribers = this.subscribers.get(type);
    if (eventSubscribers?.size > 0) {
      eventSubscribers.forEach((callback) => callback(type, payload));
    } else {
      const stickies = this.stickyEvents.get(type) || [];
      this.stickyEvents.set(type, [...stickies, payload]);
    }
  }
}

以这种方式使用时:


type Evt = "add" | "remove";
type AddPayload = { name: string };
type RemovePayload = { id: string };

type MP = {
  add: AddPayload;
  remove: RemovePayload;
};


const eb = new EventBus<Evt, MP>();

eb.subscribe("add", (type, payload) => {
  console.log(type, payload);
})

subscribe 函数中的有效负载类型不仅仅是 。打字稿是否根本不支持这一点,或者有没有办法解决它?AddPayload | RemovePayloadAddPayload

打字稿 铸造

评论

0赞 merryweather 10/20/2023
您可以使用泛型: tsplay.dev/N7Q2EW 你不必像我那样编写断言,但肯定需要某种黑客才能使其工作。

答: 暂无答案