在此代码中
document.addEventListener('keydown', (e: SyntheticKeyboardEvent<Document>) => {
if (e.ctrlKey && e.shiftKey && e.code === 'KeyE' && !this.state.envChangePopupOpened) {
this.openPopup();
}
});
Flow给出了2个似乎并非如此的问题。
首先,它给出了这个隐秘的消息:
Cannot call `document.addEventListener` because: Either string [1] is incompatible with enum [2]. Or string [1] is incompatible with enum [3]. Or `KeyboardEvent` [4] is incompatible with `SyntheticKeyboardEvent` [5] in the first argument. Or string [1] is incompatible with enum [6]. Or string [1] is incompatible with string literal `wheel` [7]. Or string [1] is incompatible with enum [8]. Or string [1] is incompatible with enum [9]. Or string [1] is incompatible with enum [10]. Or string [1] is incompatible with enum [11]. Or string [1] is incompatible with enum [12]. Or `Event` [13] is incompatible with `SyntheticKeyboardEvent` [5] in the first argument. (References: [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13])
第二个给出:
property `code` is missing in `SyntheticKeyboardEvent` [1]. (References: [1])
但是应该在e上。
您如何处理这些问题?
编辑:
事实证明,第二个问题在SyntheticEvent中不受支持,应该解决。
答案 0 :(得分:2)
问题在于SyntheticKeyboardEvent
是通过React的事件系统处理的事件的类型。因为您是直接呼叫document.addEventListener
,所以不会收到综合事件;您将获得一个本地事件。本机键盘事件的类型为KeyboardEvent
,它在Flow的内置DOM type definitions中定义。您可以像这样更改事件类型:
document.addEventListener('keydown', (e: KeyboardEvent) => {
if (e.ctrlKey && e.shiftKey && e.code === 'KeyE' && !this.state.envChangePopupOpened) {
this.openPopup();
}
});
KeyboardEvent
类型确实具有code
属性。
要了解为什么错误消息如此奇怪,您可以查看Flow的addEventListener
内置定义,并查看它具有许多重载签名。原因是不同事件类型的事件对象具有不同的属性。 (code
和shiftKey
属性是很好的示例。)addEventListener
的重载签名将特定事件类型与相应的事件对象类型相关联。这是您要使用的重载:
addEventListener(
type: KeyboardEventTypes,
listener: KeyboardEventListener,
optionsOrUseCapture?: EventListenerOptionsOrUseCapture
): void;
这是键盘事件类型的定义:
type KeyboardEventTypes = 'keydown' | 'keyup' | 'keypress';
每个重载签名的type
参数都使用类似的枚举类型。您会收到一条漫长而复杂的错误消息,因为其中一个参数存在类型不匹配,并且Flow不确定addEventListener
的许多重载签名中,哪一个是您想要的。消息string is incompatible with enum
告诉您,如果您对type
使用不同的参数,则会得到不同的签名,而据Flow所知,这可能可以解决问题。
当然,使用不同的type
参数不是问题的根源。错误消息中还有另一条线索Or KeyboardEvent [4] is incompatible with SyntheticKeyboardEvent
,可为您指出回调中事件值的正确事件类型。
在其他情况下,您可以从回调参数中删除类型注释,并让Flow推断正确的类型。但是由于addEventListener
已超载,因此Flow在这种情况下无法推断事件类型。