javascript - לזהות אם לחיצה הייתה בתוך רכיב React או לא ב-TypeScript
יש לי בערך את הדברים הבאים:
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 עושה ס sentido, מכיוון ש-e.target הוא EventTarget שנראה שמגדיר רק את הפונקציות להוספה ולהסרה של מטפלי אירועים. עם זאת MDN אומר ש- e.target הוא "הפנייה לאובייקט ששלח את האירוע." שנשמע קרוב יותר למה שאני רוצה.
אז איך אני שומר על הפונקציונליות שעובדת כרגע, תוך כדי גם לגרום ל-tsc להיות מרוצה (בניגוד פשוט להשתיק את השגיאה)?
תשובה #1
מצאתי דיון דומה בתור בעיות של TypeScript שאומר שבמקרה זה סביר שהצהרת טיפוס היא בלתי נמנעת:
ביסודו של דבר EventTarget הוא הסוג הכללי ביותר, ש-Element הוא תת-סוג שלו, ו-HTMLElement הוא תת-סוג של זה. אם אתה מקבל חפץ מה-DOM, בדרך כלל אין לנו מושג איזה הוא, ועליך להוסיף assertion של סוג כדי "להכניס" את הידע החיצוני הספציפי שיש לך על מבנה ה-DOM הספציפי שלך.
אפשרי, לדוגמה, שה-.target של אירוע אינו אלמנט (אתה יכול להוסיף מאזיני אירועים ל-XMLHttpRequest, לדוגמה, ו-XMLHttpRequest אין לו שיטה getBoundingClientRect).
אז כיוון שהיעד עשוי או לא עשוי להיות Node כפי שאני רוצה, TS לא יכולה להסיק את האמת, ואני צריך לאשר.
contains(e.target as Node) נראה כפתרון הנכון.
תשובה #2
מה אם נגדיר את מטפל ההקלקות שלך כך:
private click = (e: Event) =>
{
if (e.target instanceof HTMLElement && !ReactDOM.findDOMNode(this.someRef).contains(e.target))
{
if (this.state.toggled)
{
this.setState({ toggled: false });
}
}
}
עט לדוגמה.
