In my code, I have a discriminated union that describes different event types. The addEventHandler
function is used to add an event handler by providing the event ID as the first argument and the event callback as the second argument. The event ID field serves as the discriminator for the union type.
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) => {
// My issue is that event is not inferred to be of type TestEventC, instead it is a combination of various types
// 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
}
});
I am struggling with how to enforce the callback function within addEventHandler
to infer the correct type of the event. Any suggestions?