Typescript: EventTarget does not extend HTMLElement

Created on 23 Jan 2019  Â·  6Comments  Â·  Source: microsoft/TypeScript

TypeScript Version: 3.2.4


Search Terms:

event.target instanceof HTMLElement eventTarget not instanceof HTMLElement

Code

// event.target is instanceof HTMLElement
document.querySelector("div").addEventListener("click", (event) => {
    // shows error: "EventTarget is missing the following properties from HTMLElement ..."
    let t: HTMLElement = event.target;

    // Though:
    console.log(event.target instanceof HTMLElement) //true
})

Expected behavior:

The interface EventTarget should extend HTMLElement or event.target should return HTMLElement

Actual behavior:

EventTarget is missing the following properties from HTMLElement ...

Playground Link:

https://www.typescriptlang.org/play/index.html#src=%2F%2FNot%20relevant%0D%0Alet%20div%20%3D%20document.createElement(%22div%22)%3B%0D%0Adiv.style.width%20%3D%20%22100px%22%3B%0D%0Adiv.style.height%20%3D%20%22100px%22%3B%0D%0Adiv.style.background%20%3D%20%22red%22%3B%0D%0Adocument.querySelector(%22body%22).append(div)%3B%0D%0A%0D%0A%2F%2Frelevant%0D%0Adocument.querySelector(%22div%22).addEventListener(%22click%22%2C%20(e)%20%3D%3E%20%7B%0D%0A%09let%20t%3A%20HTMLElement%20%3D%20e.target%3B%0D%0A%0D%0A%09console.log(e.target%20instanceof%20HTMLElement)%3B%0D%0A%7D)

Related Issues:

Question

Most helpful comment

it's a limitation of the builtin types that not forwarding the generic type of the target.
A workaround would be:

if (event.target instanceof HTMLDivElement) {
....
}

All 6 comments

it's a limitation of the builtin types that not forwarding the generic type of the target.
A workaround would be:

if (event.target instanceof HTMLDivElement) {
....
}

The currentTarget read-only property of the Event interface identifies the current target for the event, as the event traverses the DOM. It always refers to the element to which the event handler has been attached, as opposed to Event.target, which identifies the element on which the event occurred.

Consider clicking on the SVG element in the DOM structure below:

<div>
  <svg />
</div>
document.querySelector("div").addEventListener("click", event => {
  console.log(event.target instanceof HTMLElement) // false
});

The output is false.

You should almost always be using event.currentTarget.

You should almost always be using event.currentTarget.

Even better, you should almost always be using this (if not within an arrow function):

my_element.addEventListener('click', function (e) {
  console.log(this.className)           // logs the className of my_element
  console.log(e.currentTarget === this) // logs `true`
})

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#The_value_of_this_within_the_handler

According to the DOM API, EventTarget does not extend HTMLElement — In fact, it is the other way around. HTMLElement extends Element, which extends Node, which extends EventTarget.

Even better, you should almost always be using this (if not within an arrow function)

I would argue it is strictly worse to use this since (as you pointed out) the value of it can change depending on what function syntax you're using. Using the event.currentTarget will always be the same thing on which you called .addEventListener() regardless of function syntax.

@jcready true, but if there are no other references to the event param, then using this lets you get away with defining a parameter for the handler function. I guess it depends on preferred coding style.

In either case, event.currentTarget, specified as an EventTarget object, is not guaranteed to be an instance of HTMLElement, or even Element or Node for that matter. I’d vote to close this issue.

I use Visual Studio, not Code. Currently VS 2019.
A very common scenario to use event.target is event delegation, where you have a handler on the parent, and when a child is clicked you want to test tagName or classList of event.target. It works, I've done it for years, I just don't get intellisense on "tagName" and "classList" since target is not HTMLElement, but not a problem...would be nice if I did.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jbondc picture jbondc  Â·  3Comments

MartynasZilinskas picture MartynasZilinskas  Â·  3Comments

Zlatkovsky picture Zlatkovsky  Â·  3Comments

blendsdk picture blendsdk  Â·  3Comments

CyrusNajmabadi picture CyrusNajmabadi  Â·  3Comments