簡體   English   中英

基於 TypeScript 中具有區分聯合的其他參數推斷 function 參數的類型

[英]Infering type of function argument based on other argument with discriminated union in TypeScript

我有一個描述事件類型的有區別的聯合。 然后我有addEventHandler function ,它將事件 ID 作為第一個參數,將事件回調作為第二個參數。 事件 ID 字段是聯合類型的鑒別器。

interface TestEventA {
  id: 'TestEventA';
  payload: null;
}

interface TestEventB {
  id: 'TestEventB';
  payload: TestEventBPayload;
}
interface TestEventBPayload {
  content: string;
}

interface TestEventC {
  id: 'TestEventC';
  payload: TestEventCPayload;
}
interface TestEventCPayload {
  value: number;
}

type TestEvent = (TestEventA | TestEventB | TestEventC);

function addEventHandler<T extends TestEvent['id']>(eventId: T, listener: (data: (TestEvent & { id: T })) => void) {
  eventEmitter.on(eventId, listener);
}


addEventHandler('TestEventC', (event) => {
  // I want event to be of type TestEventC, but instead it is of type
  // (TestEventA & { id: "TestEventC"; }) | (TestEventB & { id: "TestEventC"; }) | (TestEventC & { id: "TestEventC"; })

  // event.payload: Object is possibly 'null'
  // Property 'value' does not exist on type 'TestEventBPayload | TestEventCPayload'
  console.log(event.payload.value);

  if (event.id === 'TestEventC') { // redundant condition
    console.log(event.payload.value); // No error here
  }
});

如何使addEventHandler回調 function 推斷事件的類型?

作為一種解決方法,您可以創建一個將事件 ID 映射到有效負載的接口,例如:

interface TestEventBPayload {
  content: string;
}

interface TestEventCPayload {
  value: number;
}

interface Events {
  TestEventA: null,
  TestEventB: TestEventBPayload,
  TestEventC: TestEventCPayload
};

function addEventHandler<TId extends keyof Events>(
  eventId: TId,
  listener: (data: Events[TId] & { id: TId }) => void
): void {
  eventEmitter.on(eventId, listener);
}

addEventHandler('TestEventC', (event) => {
  console.log(event.value);

  if (event.id === 'TestEventC') {
    console.log(event.value);
  }
});

操場

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM