Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Getting ID of clicked element using strict type

Let us assume we want to log the ID attribute of a clicked element with the following TypeScript code:

onClick(event) {
  console.log(event.target.attributes.id.nodeValue);
}

The above function receives the clicked object as a parameter, but the type in this case is any. If I check the result of typeof event I get object. So I would modify my code as follows:

onClick(event: object) {
  console.log(event.target.attributes.id.nodeValue);
}

In this case, I receive an error in VS Code as below:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Property 'target' does not exist on type 'object'.ts(2339)

So what is up with this? Using the type any as parameter type works, the console logs the desired ID without any error, but if I decide to use a strict object as parameter type, my code does not compile. Where is the issue?

The affected HTML code is the following;

<h1 id="foo" (click)="onClick($event)">...</h1>

>Solution :

If I check the result of typeof event I get object.

That’s runtime code, so it’s the JavaScript typeof operator, which says "object" for all objects (and null).

So I would modify my code as follows…I receive an error is VS Code like below

Plain objects don’t have a target property.

The type of the event object for a click event is MouseEvent. (You’ve tagged and . If you’re using jQuery or the DOM to attach the event, it’ll be the DOM’s MouseEvent. If you’re using Angular to attach the event, it looks like it’ll also be the DOM’s MouseEvent. Caveat: I don’t use Angular.) You’d also probably want event.currentTarget.id or event.target.id rather than using the attributes collection and nodeValue, since the id attribute is a reflected property.

But, the DOM’s MouseEvent interface inherits its currentTarget property from Event, which just defines it as an EventTarget. You know that it will be an Element, but unfortunately the interface just says it’s EventTarget. (The same is true for target.)

As far as I’m aware, there’s no predefined interface for a MouseEvent that defines currentTarget as Element instead. You can reliably (in this situation) use a type assertion:

onClick(event: MouseEvent) {
    console.log((event.target as Element).id); // Or `(event.currentTarget as Element).id`
}

I don’t like type assertions, but they are sometimes necessary.

Sometimes you see people doing that same assertion slightly differently, like this:

onClick({target}: {target: Element}) {
    console.log(target.id);
}
// or
onClick({currentTarget}: {currentTarget: Element}) {
    console.log(currentTarget.id);
}

You might create a reusable type instead, like this:

interface ElementMouseEvent extends MouseEvent {
    currentTarget: Element;
    target: Element;
}

…and then use it (which is still making an assertion, but again, a safe one):

onClick(event: ElementMouseEvent) {
    console.log(event.target.id); // Or `event.currentTarget.id`
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading