简体   繁体   English

基于 TypeScript 中具有区分联合的其他参数推断 function 参数的类型

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

I have a discriminated union describing event type.我有一个描述事件类型的有区别的联合。 Then I have addEventHandler function that takes event ID as first argument and event callback as second.然后我有addEventHandler function ,它将事件 ID 作为第一个参数,将事件回调作为第二个参数。 Event ID field is discriminator of the union type.事件 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
  }
});

How do I make addEventHandler callback function infer type of the event?如何使addEventHandler回调 function 推断事件的类型?

As a workaround you can create an interface that maps event ids to payloads, like:作为一种解决方法,您可以创建一个将事件 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);
  }
});

Playground 操场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 打字稿:基于类型的可区分联合 - Typescript: Discriminated union based on type 通过 Typescript 中的其他 function 参数推断 function 参数的类型 - Infer type of function argument by other function argument in Typescript 打字稿区分联合类型无法识别 - Typescript discriminated union type not recognized 带有区分联合的打字稿条件类型 - Typescript conditional type with discriminated union Typescript function 基于参数的返回类型 - Typescript function return type based on argument 如何根据提供的类型在 TypeScript 中创建可区分联合的实例? - How to create an instance of a discriminated union in TypeScript based on a provided type? 根据 typescript function 中的另一个参数限制一个参数的类型 - limit the type of one argument based on anther argument in typescript function 根据 TypeScript 中可区分联合的参数自动推断返回类型 - Automatically infer return type based on arguments for discriminated union in TypeScript 有没有办法根据 Typescript 中的 function 的另一个参数来缩小参数的类型? - Is there a way to narrow the type of an argument based on another argument to a function in Typescript? 如何根据联合类型的接口属性确定函数的参数行为? - How to determine argument behavior of a function based on an interface property that is a union type?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM