我有一个函数onEvent
如下:
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...
}
};
我本来期望在if
子句中,eventLabel
被缩小到'finished'
,由此推断eventDetails
可以缩小到{input: number; result: number}
,从而定义了eventDetails.result
。
但这不会发生;eventDetails
的类型就是Events[keyof Events]
。为什么会这样,我该怎么做才能正确输入?
操场上联系
经过一番尝试,我找到了一个解决方案。我无法想象这是"经典的"。一个是因为它有点间接,但它有效:
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
}
};