Why typescript doesn't accept React.KeyboardEvent<HTMLInputElement>?

In my react ts app I have this code:

useEffect(() => {
    const handleEscKeyPress = (
      event: React.KeyboardEvent<HTMLInputElement> & { isComposing: boolean }
    ) => {
      if (event.isComposing || event.key === 'Escape') {
        onClose();
        return;
      }
    };

    document.addEventListener('keydown', handleEscKeyPress);

    return () => {
      document.removeEventListener('keydown', handleEscKeyPress!);
    };
  }, []);

IDE highlights document.addEventListener(‘keydown’, handleEscKeyPress); and messages:

const handleEscKeyPress: (event: React.KeyboardEvent<HTMLInputElement> & {
    isComposing: boolean;
}) => void
No overload matches this call.
  Overload 1 of 2, '(type: "keydown", listener: (this: Document, ev: KeyboardEvent) => any, options?: boolean | AddEventListenerOptions | undefined): void', gave the following error.
    Argument of type '(event: React.KeyboardEvent<HTMLInputElement> & {    isComposing: boolean;}) => void' is not assignable to parameter of type '(this: Document, ev: KeyboardEvent) => any'.
      Types of parameters 'event' and 'ev' are incompatible.
        Type 'KeyboardEvent' is not assignable to type 'KeyboardEvent<HTMLInputElement> & { isComposing: boolean; }'.
          Type 'KeyboardEvent' is missing the following properties from type 'KeyboardEvent<HTMLInputElement>': locale, nativeEvent, isDefaultPrevented, isPropagationStopped, persist
  Overload 2 of 2, '(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | undefined): void', gave the following error.
    Argument of type '(event: React.KeyboardEvent<HTMLInputElement> & {    isComposing: boolean;}) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject'.
      Type '(event: React.KeyboardEvent<HTMLInputElement> & {    isComposing: boolean;}) => void' is not assignable to type 'EventListener'.
        Types of parameters 'event' and 'evt' are incompatible.
          Type 'Event' is not assignable to type 'KeyboardEvent<HTMLInputElement> & { isComposing: boolean; }'.
            Type 'Event' is missing the following properties from type 'KeyboardEvent<HTMLInputElement>': altKey, charCode, ctrlKey, code, and 15 more.ts(2769)

What type should I assign for event to avoid this problem?

>Solution :

A React keyboard event is not the same as a keyboard event directly from the browser. document.addEventListener does not accept a callback that uses a React event.

You cannot specify that the event is on an HTMLInputElement either – that’s not the only element the keydown event can be fired on. Use just KeyboardEvent.

Because isComposing is already a property typed on the native KeyboardEvent, you can leave it off entirely.

const handleEscKeyPress = (
    event: KeyboardEvent
) => {

Also, because the function will always be defined:

document.removeEventListener('keydown', handleEscKeyPress!);

the non-null assertion is superfluous:

document.removeEventListener('keydown', handleEscKeyPress);

Leave a Reply