Here is a snippet for event delegation from :
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 attempting to rewrite it in TypeScript with type safety (specifically for handling click events):
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);
}
The TypeScript compiler is throwing an error:
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()
method belongs to the Element
interface - it cannot be called on type Node & ParentNode
.
What should be done in this case?
If
targetParentNode = targetParentNode.parentNode as Element
is correct, please provide an explanation.
P. S. Please avoid using any
, object
, or omitting type annotations.