The recipe of event delegating from http://youmightnotneedjquery.com/:
document.addEventListener(eventName, function(e) { // loop parent nodes from the target to the delegation node for (var target = e.target; target && target != this; target = target.parentNode) { if (target.matches(elementSelector)) { handler.call(target, e); break; } } }, false);
I am trying rewrite it to TypeScript type-safely (for click event for now):
export default function delegateClickEventHandling( { clickTargetSelector, container = document }: { clickTargetSelector: string; container: HTMLElement | Document; }, handler: (event: MouseEvent) => void ): void { container.addEventListener("click", (event: Event): void => { if (!(event instanceof MouseEvent)) { return; } for ( let targetParentNode: Element | null = event.target as Element; isNotNull(targetParentNode) && targetParentNode !== event.currentTarget; targetParentNode = targetParentNode.parentNode ) { if (targetParentNode.matches(clickTargetSelector)) { handler(event); } } }, false); }
TypeScript compiler tells me:
TS2322: Type '(Node & ParentNode) | null' is not assignable to type 'Element | null'. Type 'Node & ParentNode' is not assignable to type 'Element | null'. Type 'Node & ParentNode' is missing the following properties from type 'Element': assignedSlot, attributes, classList, className, and 64 more.
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:
for ( let targetParentNode: Element = event.target as Element; targetParentNode !== event.currentTarget; targetParentNode = targetParentNode.parentNode as Element ) { if (targetParentNode.matches(clickTargetSelector)) { handler(event); } }