流类型“ keydown”事件

时间:2018-12-18 13:59:37

标签: javascript flowtype

在此代码中

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中不受支持,应该解决。

1 个答案:

答案 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内置定义,并查看它具有许多重载签名。原因是不同事件类型的事件对象具有不同的属性。 (codeshiftKey属性是很好的示例。)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在这种情况下无法推断事件类型。