As JLRishe correctly said in his answer, the target field of the Event object does not have to be an Element. However, we can be sure that any event that inherits from UIEvent will always have a target field in the listener with a type that implements the Node interface, with the exception of only one case for Windows. I would present this exception this way (using the example of a click event):
window.addEventListener('click', e => {
console.log(e.target) // Window
console.log(e.target instanceof Node) // false
}
window.dispatchEvent(new MouseEvent('click'))
In all other cases, it will be any type inherited from Node
.
Why Node and not Element?
That's a good question. It is fair to say that if an event is triggered natively by user interaction with the GUI, then it will always be a type implementing Element. But it still remains possible to call any UIEvent artificially:
const node = document.createTextNode('')
document.body.appendChild(node)
window.addEventListener('click', e => {
console.log(e.target instanceof Element)) // false
}
node.dispatchEvent(new MouseEvent('click', {bubbles: true}))
And although this example is from a spherical vacuum, it is possible.
All this is very interesting, but difficult. And that's why I suggest using a package that provides for all possible cases and automatically outputs safe types. That's package is types-spring. For clarity:
listener is HTMLElement
original types:
const elem = document.querySelector('div')
if (elem) elem.addEventListener('click', e => {
e.target // EventTarget| null
if (e.currentTarget)
{
e.currentTarget // EventTarget
}
})
with types-spring:
const elem = document.querySelector('div')
if (elem) elem.addEventListener('click', e => {
e.target // Node | null
if (e.currentTarget)
{
e.currentTarget // HTMLDivElement
}
})
Listener is Window
original types:
window.addEventListener('click', e => {
if (e.target) {
if (e.isTrusted === true) {
e.target // is EventTarget
}
if (e.target instanceof Window) {
e.target // is Window
}
else {
e.target // is EventTarget
}
}
})
with types-spring:
window.addEventListener('click', e => {
if (e.target) {
if (e.isTrusted === true) {
e.target // is Element
}
if ('atob' in e.target) {
e.target // is Window
}
else {
e.target // is Node
}
}
})
I hope the package helps with routine development
PS: Any ideas about this one?
var element = ev.target as HTMLElement
– Paleopsychology