[英]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);
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.