I'm trying to define a strongly typed event-emitter, what I mostly want is to have the callback's event type inferred from the string passed to the addEventHandler
function.
But I've failed so far, and what I came up with infers the event type from the callback, not the opposite.
Here's an example (with a fiddle):
interface NumberEvent {
type: 'NumberEvent';
num: number;
}
interface StringEvent {
type: 'StringEvent';
str: string;
}
type AnyEvent = NumberEvent | StringEvent;
const addEventHandler = <ET extends AnyEvent>(type: ET['type'], handler: ((event: ET) => void)) => {
console.log(`added event handler for ${type}`);
}
addEventHandler('NumberEvent', (event: NumberEvent) => {
// this is cool
});
addEventHandler('NumberEvent', (event: StringEvent) => {
// this doesn't type check, good
});
addEventHandler('type does not exist', (x: any) => {
// why no type error?
});
I do not understand why the last line type-checks, because there is no instance of AnyEvent
with type 'type does not exist'
.
Can you think of a better approach to the problem?