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
}