Reputation: 6491
I have a custom event listener hook that looks like this:
const useEventListener = (
eventName: string,
handler: ({key} : KeyboardEvent) => void,
) => {
const savedHandler = useRef<({key} : KeyboardEvent) => void>(handler)
useEffect(() => {
savedHandler.current = handler
}, [handler])
useEffect(() => {
const eventListener = (event: KeyboardEvent) => savedHandler.current(event)
window.addEventListener(eventName, eventListener);
return () => {
window.removeEventListener(eventName, eventListener)
}
}, [eventName])
}
This is throwing the error,
TS error: Type 'event' is missing the following properties from type 'keyboardevent': char, key and 18 others
Am I typing the useRef incorrectly? I wasn't able to find anything from here that work either. Not sure what I'm doing wrong here.
Upvotes: 7
Views: 13311
Reputation: 5988
It's OK.
Working solutions will be
const useEventListener = (
eventName: 'keydown' | 'keyup',
handler: ({key} : KeyboardEvent) => void,
) => {
const savedHandler = useRef<({key} : KeyboardEvent) => void>(handler)
useEffect(() => {
savedHandler.current = handler
}, [handler])
useEffect(() => {
const eventListener = (event: KeyboardEvent) => savedHandler.current(event)
window.addEventListener(eventName, eventListener);
return () => {
window.removeEventListener(eventName, eventListener)
}
}, [eventName])
}
The issue was eventName: string,
TS sees that you are allowing to listen for any event (keyboard or not) so it can't guarantee that the emitted event will be only keyboard type. So you need to assure TS that you will listen only for keyboard events. This can be done by providing the correct type for the eventName which should be a subset of the keyboard event names.
That's it.
Upvotes: 7