流式'keydown'事件

Hay*_*yan 5 javascript flowtype

在这段代码中

document.addEventListener('keydown', (e: SyntheticKeyboardEvent<Document>) => {
    if (e.ctrlKey && e.shiftKey && e.code === 'KeyE' && !this.state.envChangePopupOpened) {
        this.openPopup();
    }
 });
Run Code Online (Sandbox Code Playgroud)

Flow给出了两个似乎不是这样的问题.

首先,它给出了这个神秘的信息:

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])
Run Code Online (Sandbox Code Playgroud)

第二个给出:

property `code` is missing in `SyntheticKeyboardEvent` [1]. (References: [1])
Run Code Online (Sandbox Code Playgroud)

但它应该是e.

你怎么处理这些?

编辑:

第二个问题结果是SyntheticEvent不支持,应该解决.

Jes*_*ett 4

问题是这SyntheticKeyboardEvent是通过 React 事件系统处理的事件类型。因为您直接调用,document.addEventListener所以不会得到合成事件;您将得到一个本机事件。本机键盘事件的类型是KeyboardEvent在 Flow 的内置DOM 类型定义中定义的。您可以像这样更改事件类型:

document.addEventListener('keydown', (e: KeyboardEvent) => {
    if (e.ctrlKey && e.shiftKey && e.code === 'KeyE' && !this.state.envChangePopupOpened) {
        this.openPopup();
    }
 });
Run Code Online (Sandbox Code Playgroud)

KeyboardEvent类型确实有一个code属性。

要理解为什么错误消息如此奇怪,您可以查看 Flow 的内置定义addEventListener,并看到它有许多重载的签名。原因是不同事件类型的事件对象具有不同的属性。(code和属性就是很好的例子。)用于将特定事件类型与相应事件对象类型相关联的shiftKey重载签名。addEventListener这是您要使用的重载:

addEventListener(
  type: KeyboardEventTypes,
  listener: KeyboardEventListener,
  optionsOrUseCapture?: EventListenerOptionsOrUseCapture
): void;
Run Code Online (Sandbox Code Playgroud)

这是键盘事件类型的定义:

type KeyboardEventTypes = 'keydown' | 'keyup' | 'keypress';
Run Code Online (Sandbox Code Playgroud)

每个重载签名都使用类似的枚举类型作为其type参数。您会收到一条长而复杂的错误消息,因为其中一个参数存在类型不匹配,并且 Flow 无法确定众多重载签名中的哪一个addEventListener是您想要的。这些消息告诉string is incompatible with enum您,如果您使用不同的参数,type您将获得不同的签名,据 Flow 所知,这也许可以解决问题。

当然,使用不同的type参数并不是问题的根源。错误消息中还有另一条线索,Or KeyboardEvent [4] is incompatible with SyntheticKeyboardEvent它指出回调中事件值的正确事件类型。

在其他情况下,您可以从回调参数中删除类型注释,并让 Flow 推断正确的类型。但由于addEventListenerFlow 过载,在这种情况下无法推断事件类型。