我大致有以下几点:
componentDidMount() {
document.querySelector('body')!.addEventListener('click', this.click);
}
click = (e: Event) => {
if (this.state.toggled) {
if (!ReactDom.findDOMNode(this.someRef).contains(e.target)) {
this.setState({ toggled: false });
}
}
};
render() {
return (<CustomElement
ref={(e) => { this.someRef = e; }}
/>)
}
此代码正确检测用户是在 CustomElement 内部还是外部单击,目前一切顺利。
但是,tsc
对此一点都不满意:
error TS2345: Argument of type 'EventTarget' is not assignable to parameter of type 'Node'.
Property 'attributes' is missing in type 'EventTarget'.
查看 node_modules/typescript/lib/lib.d.ts
这是有道理的,因为 e.target
是一个 EventTarget
出现仅定义用于添加和删除事件处理程序的函数。然而MDN说 e.target 是“对调度事件的对象的引用”。这听起来更接近我想要的。
那么我该如何保留当前可用的功能,同时让 tsc 满意(而不是仅仅消除错误)?
最佳答案
我在 typescript issue queue 中发现了类似的讨论在这种情况下,类型断言是 probably unavoidable :
Basically EventTarget is the most general type, of which Element is a subtype, and HTMLElement is a subtype of that. If you get back a thing from the DOM, we generally have no idea which it is, and you should add a type assertion to "add in" the specific external knowledge that you have about the structure of your particular DOM layout.
It's possible, for example, that the .target of an event is not an Element (you can add event listeners to XMLHttpRequest, for example, and XMLHttpRequest does not have a getBoundingClientRect method).
所以因为 target 可能是也可能不是我想要的 Node
,TS 无法推断出真相,我需要断言。
contains(e.target as Node)
似乎是正确的解决方案。
关于javascript - 检测点击是否在 react 组件内部或不在 typescript 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43842057/