Home > Net >  Typescript addEventListener to keydown giving error
Typescript addEventListener to keydown giving error

Time:04-28

I want to remove and add event listeners to HTML elements that can focus (in this case buttons) but I am seeing a typescript error on the lines of code that add and remove the event listener:

  focusableElements.forEach((el) => {
      el.removeEventListener('keydown', focus); 
      el.addEventListener('keydown', focus);
  });

focus accepts a KeyboardEvent like so

const focus = (evt: KeyboardEvent) => {
    .... in here we have code that uses evt.key and evt.shiftKey
}

this is the exact error I am seeing

No overload matches this call.
  Overload 1 of 2, '(type: keyof ElementEventMap, listener: (this: Element, ev: Event) => any, options?: boolean | EventListenerOptions | undefined): void', gave the following error.
    Argument of type '"keydown"' is not assignable to parameter of type 'keyof ElementEventMap'.
  Overload 2 of 2, '(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions | undefined): void', gave the following error.
    Argument of type '(evt: KeyboardEvent) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject'.
      Type '(evt: KeyboardEvent) => void' is not assignable to type 'EventListener'.
        Types of parameters 'evt' and 'evt' are incompatible.
          Type 'Event' is missing the following properties from type 'KeyboardEvent': altKey, charCode, code, ctrlKey, and 17 more.

I tried changing KeyboardEvent to Event but that brings about other errors inside of focus due to the fact that we are using evt.key and evt.shiftKey.

CodePudding user response:

The reason behind this error is that the existing definitions for EventListeners are very broad and generic in the sense, that the overloads provided don't define it for all the possible Event Types such as Mouse, Keyboard, etc.

But we can create our own overload for this based on our requirements hence for this use case this would solve it!

Now we have created two more overloads to handle our special scenario.

let focusableElements: Element[] = [];

interface Element {
  removeEventListener(type: 'keyup' | 'keydown', listener: (event: KeyboardEvent) => any, options?: boolean | EventListenerOptions): void;
  addEventListener(type: 'keyup' | 'keydown', listener: (event: KeyboardEvent) => any, options?: boolean | EventListenerOptions): void;

}

focusableElements.forEach((el) => {
      el.removeEventListener('keydown', focus_);
      el.addEventListener('keydown', focus_);
  });


const focus_ = (evt: KeyboardEvent) => {
    evt.key // works fine
    evt.shiftKey //perfectly fine
}


Code Playground

  • Related