[英]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.