Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flow type 'keydown' event

In this code

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

Flow gives 2 issues which seem to not be as such.

First it gives this cryptic message:

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])

and second gives:

property `code` is missing in `SyntheticKeyboardEvent` [1]. (References: [1])

But it should be on e.

How do you handle these?

EDIT:

The second issue turns out is not supported in SyntheticEvent and should be worked around.

like image 707
Hayk Safaryan Avatar asked Dec 18 '18 13:12

Hayk Safaryan


People also ask

What are event type are Keydown?

The keydown event is fired when a key is pressed. Unlike the deprecated keypress event, the keydown event is fired for all keys, regardless of whether they produce a character value. The keydown and keyup events provide a code indicating which key is pressed, while keypress indicates which character was entered.

How do you get the value of a Keydown event?

The simple solution: just use the keyup event (and not the keydown event). This will give you the latest value after the user typed the latest character. That resolves the issue.

Which are the not types of key events?

5. Which of the following are not key event properties? Explanation: altKey, ctrlKeY, shiftKey, and metaKey are key event object's properties, which are set to true if the corresponding modifier key is held down when the event occurs.

What is a key event in a text?

An event which indicates that a keystroke occurred in a component. This low-level event is generated by a component object (such as a text field) when a key is pressed, released, or typed.


1 Answers

The problem is that SyntheticKeyboardEvent is a type for events that are handled through React's event system. Because you are calling document.addEventListener directly you will not get a synthetic event; you will get a native event instead. The type for native keyboard events is KeyboardEvent which is defined in Flow's built-in DOM type definitions. You can change the event type like this:

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

The KeyboardEvent type does have a code property.

To understand why the error message is so weird you can look at Flow's built-in definition for addEventListener, and see that it has many overloaded signatures. The reason for this is that event objects for different event types come with different properties. (The code and shiftKey properties are good examples.) The overloaded signatures for addEventListener relate specific event types to corresponding event object types. This is the overload you want to use:

addEventListener(
  type: KeyboardEventTypes,
  listener: KeyboardEventListener,
  optionsOrUseCapture?: EventListenerOptionsOrUseCapture
): void;

This is the definition for the keyboard event types:

type KeyboardEventTypes = 'keydown' | 'keyup' | 'keypress';

Each overloaded signature uses a similar enum type for its type parameter. You get a long, complicated error message because there is a type mismatch in one of the arguments, and Flow does not know for certain which of the many overloaded signatures of addEventListener is the one that you want. The messages saying string is incompatible with enum inform you that if you use a different argument for type you will get a different signature, and as far as Flow knows maybe that could fix the problem.

Of course using a different type argument is not the source of your problem. There is another clue in the error message, Or KeyboardEvent [4] is incompatible with SyntheticKeyboardEvent which points you to the proper event type for the event value in your callback.

In other circumstances you could remove the type annotation from the callback argument, and let Flow infer the correct type. But because addEventListener is overloaded Flow cannot infer the event type in this case.

like image 168
Jesse Hallett Avatar answered Oct 05 '22 23:10

Jesse Hallett