The recipe of event delegating from http://youmightnotneedjquery.com/:
JavaScript
x
10
10
1
document.addEventListener(eventName, function(e) {
2
// loop parent nodes from the target to the delegation node
3
for (var target = e.target; target && target != this; target = target.parentNode) {
4
if (target.matches(elementSelector)) {
5
handler.call(target, e);
6
break;
7
}
8
}
9
}, false);
10
I am trying rewrite it to TypeScript type-safely (for click event for now):
JavaScript
1
31
31
1
export default function delegateClickEventHandling(
2
{
3
clickTargetSelector,
4
container = document
5
}: {
6
clickTargetSelector: string;
7
container: HTMLElement | Document;
8
},
9
handler: (event: MouseEvent) => void
10
): void {
11
12
container.addEventListener("click", (event: Event): void => {
13
14
if (!(event instanceof MouseEvent)) {
15
return;
16
}
17
18
for (
19
let targetParentNode: Element | null = event.target as Element;
20
isNotNull(targetParentNode) && targetParentNode !== event.currentTarget;
21
targetParentNode = targetParentNode.parentNode
22
) {
23
24
if (targetParentNode.matches(clickTargetSelector)) {
25
handler(event);
26
}
27
}
28
}, false);
29
}
30
31
TypeScript compiler tells me:
JavaScript
1
5
1
TS2322: Type '(Node & ParentNode) | null' is not assignable to type 'Element | null'.
2
Type 'Node & ParentNode' is not assignable to type 'Element | null'.
3
Type 'Node & ParentNode' is missing the following properties from type 'Element':
4
assignedSlot, attributes, classList, className, and 64 more.
5
The .matches()
is the method of the Element
– I can’t to call it from Node & ParentNode
).
What have I do?
If targetParentNode = targetParentNode.parentNode as Element
is completely all right please explain why.
P. S. Please note that any
, object
and type annotation omitting are not allowed.
Advertisement
Answer
You just need to cast targetParentNode.parentNode
to Element
.
So for loop
might be look like this:
JavaScript
1
11
11
1
for (
2
let targetParentNode: Element = event.target as Element;
3
targetParentNode !== event.currentTarget;
4
targetParentNode = targetParentNode.parentNode as Element
5
) {
6
7
if (targetParentNode.matches(clickTargetSelector)) {
8
handler(event);
9
}
10
}
11