I'm working on a Next.js app, and I found out that the type I assigned to the event throws me an error.
Here is my code so far:
const keyboard = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!showKeyboard) return; // If the keyboard is not shown then we don't need a listener to hide it, so we stop here.
// Hide the keyboard if a click was triggered outside the keyboard.
function hideKeyboard(event: Event) {
if (
keyboard.current &&
event != null &&
!keyboard.current.contains(event?.target)
) {
setShowKeyboard(false);
}
}
window.addEventListener('click', hideKeyboard);
return () => window.removeEventListener('click', hideKeyboard); // Remove the listener.
}, [showKeyboard]);
The app runs and works as expected, however an error is thrown by TypeScript:
TS2345: Argument of type 'EventTarget | null' is not assignable to parameter of type 'Node | null'.<br/>Type 'EventTarget' is missing the following properties from type 'Node': baseURI, childNodes, firstChild, isConnected, and 43 more.
I have also tried React.MouseEvent<Window>
and React.MouseEvent<HTMLElement>
. However, the same error is thrown plus the next one:
No overload matches this call.
Overload 1 of 2, '(type: "click", listener: (this: Window, ev: MouseEvent) => any, options?: boolean | EventListenerOptions | undefined): void', gave the following error.
Argument of type '(event: MouseEvent<HTMLElement, MouseEvent>) => void' is not assignable to parameter of type '(this: Window, ev: MouseEvent) => any'.
Types of parameters 'event' and 'ev' are incompatible.
Type 'MouseEvent' is missing the following properties from type 'MouseEvent<HTMLElement, MouseEvent>': nativeEvent, isDefaultPrevented, isPropagationStopped, persist Overload 2 of 2, '(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions | undefined): void', gave the following error.
Argument of type '(event: MouseEvent<HTMLElement, MouseEvent>) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject'.
Type '(event: MouseEvent<HTMLElement, MouseEvent>) => void' is not assignable to type 'EventListener'. Types of parameters 'event' and 'evt' are incompatible. Type 'Event' is missing the following properties from type 'MouseEvent<HTMLElement, MouseEvent>': altKey, button, buttons, clientX, and 18 more.
My code works as expected in all the 3 types I have tried. The only way for me to hide the TS errors is using any
, but that is not the best practice. Thanks in advance!
If you hover over addEventListener
, TypeScript tells you that the correct definition for a click handler for the window
object would be (this: Window, ev: MouseEvent) => any
.
Beyond that, for hideKeyboard
, you would need an event.target instanceof Node
check, as contains()
expect a Node
element and event.target
is of type EventTarget | null
.
function hideKeyboard(this: Window, event: MouseEvent):any {
if (!showKeyboard) return;
if (
keyboard.current &&
event.target instanceof Node &&
!keyboard.current.contains(event.target)
) {
setShowKeyboard(false);
}
}