【问题标题】:Flow type 'keydown' event流式'keydown'事件
【发布时间】:2019-05-18 23:13:55
【问题描述】:

在这段代码中

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 不支持第二个问题,应该解决。

【问题讨论】:

  • 根据this 问题,我认为尚不支持代码。

标签: javascript flowtype


【解决方案1】:

问题在于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无法推断事件类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-18
    • 2016-03-18
    • 2014-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多