Issue
I import MouseEvent from react
import { MouseEvent } from 'react';
Use MouseEvent in the following
const closeSelectBox = (e: MouseEvent): void => {
if (!searchOptionWrapRef.current?.contains(e.target)) {
setOpenSelectBox(false)
}
};
I listen to my closeSelectBox
useEffect(() => {
document.addEventListener("click", closeSelectBox);
return () => {
document.removeEventListener("click", closeSelectBox);
};
}, [])
searchOptionWrapRef is a div
const searchOptionWrapRef = useRef<HTMLDivElement>(null);
<div ref={searchOptionWrapRef}/>
But I get the following error
Argument of type 'EventTarget' is not assignable to parameter of type 'Node'.
Type 'EventTarget' is missing the following properties from type 'Node': baseURI, childNodes, firstChild, isConnected, and 43 more.
How do I resolve this type error without using any in place of MouseEvent?
Solution
The event interfaces exported by React are for React event handler props, not addEventListener handlers. For those, don't import MouseEvent from React and you'll get the DOM global interface for it instead, which works with addEventListener. And yes, it's confusing. :-)
But the second issue (which actually may be your main issue) is that the DOM global MouseEvent defines target as an EventTarget, not as a Node. In your case, it'll always be a Node (specifically, an Element), but that's how the DOM type is defined. To deal with that, you have at least two choices:
Purist
You could go really purist (I do) and use a type assertion function to assert that target is a Node:
// In a utility library:
function assertIsNode(e: EventTarget | null): asserts e is Node {
if (!e || !("nodeType" in e)) {
throw new Error(`Node expected`);
}
}
// And then in your component:
const closeSelectBox = ({target}: MouseEvent): void => {
assertIsNode(target);
if (!searchOptionWrapRef.current?.contains(target)) {
setOpenSelectBox(false);
}
};
Concise and Pragmatic
You know that target is a Node and isn't null, so you could use a type assertion (target as Node):
const closeSelectBox = ({target}: MouseEvent): void => {
if (!searchOptionWrapRef.current?.contains(target as Node)) {
setOpenSelectBox(false);
}
};
I don't like type assertions that aren't checked at runtime (which is what a type assertion function like assertIsNode does), so I'd probably go with the first approach. But in limited situations where you're sure about it, you might consider one.
Answered By - T.J. Crowder
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.