'How to correctly type generic function with two parameters that depend on the generic?
I have a function onEvent as follows:
interface Events {
'finished': {
input: number;
result: number;
};
'error': {
input: number;
error: Error;
};
}
const onEvent = <K extends keyof Events>(eventLabel: K, eventDetails: Events[K]) => {
if (eventLabel === 'finished') {
console.log(eventDetails.input); // works, probably because 'input' is defined on both events.
console.log(eventDetails.result); // error ts2339: Property 'result' does not exist...
}
};
I would have expected that within the if clause, eventLabel is narrowed to 'finished', from which it is inferred that eventDetails can be narrowed to {input: number; result: number}, so that eventDetails.result is defined.
But that does not happen; the type of eventDetails is rather just Events[keyof Events]. Why is that and what can I do to get the typings right?
Solution 1:[1]
After some trying out, I found a solution. I cannot imagine it's the "canonical" one because it's a bit indirect, but it works:
const onEvent: (...args: {[k in keyof Events]: [k, Events[k]]}[keyof Events]) => void =
(eventLabel, eventDetails) => {
if (eventLabel === 'finished') {
console.log(eventDetails.input); // works, probably because 'input' is defined on both events.
console.log(eventDetails.result); // works now too
}
};
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Remirror |
