I'have the following error even if the code run perfectly:
"TS2345: Argument of type 'Event' is not assignable to parameter of type 'KeyboardEvent'.
Property 'altKey' is missing in type 'Event'."
// In a Class
public listenTo = (window: Window) => {
['keydown', 'keyup'].forEach(eventName => {
window.addEventListener(eventName, e => {
this.handleEvent(e); // <- error here
});
});
}
public handleEvent = (event: KeyboardEvent) => {
const { key } = event;
//...
}
I tried to define the event type to KeyboardEvent, but I have the following error :
window.addEventListener(eventName, (e:KeyboardEvent) => {
this.handleEvent(e); // <- error here
});
TS2345: Argument of type '(event: KeyboardEvent) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject'.
Type '(event: KeyboardEvent) => void' is not assignable to type 'EventListenerObject'.
Property 'handleEvent' is missing in type '(event: KeyboardEvent) => void'.
Is there a way to pass through or resolve the issue ?
TypeScript isn't able to make the full leap here, because all it knows is the event name will be a string, so the most general event type is used.
Examples below converted to a stand alone running example - so I've taken things "out of a class" for the demo...
While the strings are keydown
and keyup
you can guarantee the type safety, and overrule the compiler:
let listenTo = (window: Window) => {
['keydown', 'keyup'].forEach(eventName => {
window.addEventListener(eventName, e => {
handleEvent(<any>e);
});
});
}
let handleEvent = (event: KeyboardEvent) => {
const { key } = event;
//...
}
This would fall down if some other string was added to your array of event names.
Full type safety is available when using a string directly, due to specialized signatures:
window.addEventListener('keydown', e => {
handleEvent(e); // e is KeyboardEvent
});
So you could type your array more strongly to get the correct types goodness:
type KeyboardEventNames = 'keydown' | 'keyup';
let listenTo = (window: Window) => {
const eventNames: KeyboardEventNames[] = ['keydown', 'keyup'];
eventNames.forEach(eventName => {
window.addEventListener(eventName, e => {
handleEvent(e);
});
});
}
let handleEvent = (event: KeyboardEvent) => {
const { key } = event;
//...
}
In this last example, we restict the type of elements in the array to only keyboard event names, so the compiler now knows it isn't dealing with just any old string, and can infer the event type.
The strings 'keyup'
and 'keydown'
are already known string literal types. However, strings in your code are not candidates for checking against known string literal types unless they are const
. Simply make yours constant:
public listenTo = (window: Window) => {
['keydown' as const, 'keyup' as const].forEach(eventName => {
window.addEventListener(eventName, e => {
this.handleEvent(e);
});
});
}
or
public listenTo = (window: Window) => {
(['keydown', 'keyup'] as const).forEach(eventName => {
window.addEventListener(eventName, e => {
this.handleEvent(e);
});
});
}
depending on your tastes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With