Skip to content
tezvyn:

Describe event delegation and implement a single ul click handler in TypeScript

Source: developer.mozilla.orgMediumHow cards are made

Describe event delegation and implement a single ul click handler in TypeScript
Summary

Event bubbling and parent-level listener efficiency.

Key points

Add one listener to the ul, use event.target plus closest to find the li, and type it as MouseEvent.

Watch out for

Attaching listeners to each li or leaving event.target untyped.

What's really being asked

This question probes your understanding of the DOM event propagation model, specifically bubbling, and whether you know how to scale event handling without linear growth in listeners. It also checks TypeScript fluency: can you correctly type the event object and safely narrow event.target to the intended element type.

The full answer

First, a concise explanation of event bubbling: when a user clicks an li, the browser fires a click event on that li and then walks up the ancestor chain, allowing the ul to hear the event. Second, the implementation strategy: select the ul, call addEventListener with a handler typed as (e: MouseEvent) => void, and inside the handler use e.target to locate the originating element. Third, the critical safety step: because e.target could be a nested element inside the li such as a span or icon, use Element.closest('li') to walk upward and find the actual list item; if the click lands on the ul padding outside any li, closest returns null so you guard against that. Fourth, mention the performance and memory win: one listener versus hundreds, which matters on large lists and avoids leaks when items are dynamically added or removed.

The mistakes people make

A red flag is suggesting document.querySelectorAll('li') and attaching a listener to each node; this defeats the purpose and creates O(n) listener overhead. Another mistake is assuming e.target is always the li and immediately casting it without checking, which breaks when clicks hit nested tags. Some candidates forget TypeScript types entirely and write untyped event parameters or use any, which signals weak type safety habits. A subtle error is using e.currentTarget expecting it to point to the li; currentTarget is the ul where the listener lives, not the clicked child.

What usually comes next

The interviewer may ask how you would handle dynamic items added after the listener is registered, which delegation handles naturally while individual listeners do not. They might ask about event capturing versus bubbling, or how stopPropagation affects delegation. Another follow-up is how to strongly type the li element inside the handler, perhaps using a type guard or generic with closest.

A concrete example

In TypeScript, you might write: const list = document.querySelector('ul'); if (!list) return; list.addEventListener('click', (event: MouseEvent) => { const target = event.target as HTMLElement; const li = target.closest('li'); if (!li) return; console.log('Clicked item:', li.textContent); }); This attaches one listener, safely narrows the target, ignores clicks on the ul background, and scales to any number of items.

Interview question

Which TypeScript approach correctly handles clicks on a ul containing li elements with nested child elements?

  • a.Attach a click listener to every li with querySelectorAll('li'), typing the event as MouseEvent.
  • b.Add one click listener to the ul, use (event.target as HTMLElement).closest('li') to find the list item, and guard against null.Correct
  • c.Add one click listener to the ul and use event.currentTarget.closest('li') to identify the clicked item.
  • d.Add one click listener to the ul, cast event.target directly to HTMLLIElement, and read its textContent.
Why?

Option B correctly leverages event delegation and safely walks up from nested elements via closest('li'), guarding against clicks on the ul padding. Option D is tempting but fails when event.target is a nested span rather than the li itself.

Just read this? Test yourself on what you have been reading.

Read the original → developer.mozilla.org

You just looked this up. Could you explain it out loud?

That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Every open role lists the topics its interview covers, so you can prepare for the real thing rather than guessing.

See open roles