Let's suppose we have the following HTML element:
<div id="foo"></div>
With the following code snippet we will receive the element above as an event target in our event listener:
const elem = document.getElementById('foo');
elem.addEventListener('test', function (e) {
// Property 'id' does not exist on type 'EventTarget'.
console.log(e.target.id); // 'foo'
}, false);
elem.dispatchEvent(new Event('test'));
This code runs perfectly fine because we know we're expecting the event target to be an HTML element, and we are certain that the HTML element has the property id
. However, TypeScript complains about the id
property not existing on the EventTarget
type. This is because:
- By default an event target element has an
EventTarget
type in TypeScript; - The
EventTarget
type does not inherit from theElement
type which is why TypeScript fails to recognize properties such asid
,class
, etc. that we would expect to exist on a typicalElement
object.
Why Does the EventTarget
Type Not Inherit From Element
Type?
The reason this is the case is simply because all event targets might not be HTML elements. For example the event target can be also be XMLHttpRequest
, FileReader
, AudioNode
, AudioContext
, etc.
How to Fix This Error?
To make TypeScript understand the correct type for the event target, we can specify it like so:
const elem = document.getElementById('foo'); elem.addEventListener('test', function (e) { const target = e.target as Element; console.log(target.id); // 'foo' }, false); elem.dispatchEvent(new Event('test'));
We can also inline it like so:
(e.target as Element).id
Alternatively, we can also do the following if we only need to use the target
property from the event:
const elem = document.getElementById('foo');
elem.addEventListener('test', function (e: { target: Element }) {
console.log(e.target.id); // 'foo'
// Property 'type' does not exist on type '{ target: HTMLInputElement; }'.
console.log(e.type);
}, false);
elem.dispatchEvent(new Event('test'));
As it is evident from the example above, after specifying the correct type for e.target
it works fine. However, other properties (such as e.type
, etc.) would throw a TypeScript error. If we need to access those other properties of the event as well, we could do so in the following way:
const elem = document.getElementById('foo'); elem.addEventListener('test', function (e: Event & { target: Element }) { console.log(e.target.id); // 'foo' // other Event object properties are recognized too now: console.log(e.type); // 'test' }, false); elem.dispatchEvent(new Event('test'));
We can, of course, get more specific with the type of the target events. For example, let's suppose we wanted to get the value
attribute of the following target input
element:
<input id="foo" type="text" value="bar" />
Without setting the proper type for the event target, we'll get the "Property 'value' does not exist on type 'EventTarget'
" error while trying to get the value
property of the input
element. Therefore, as discussed earlier, we need to assert the type we expect the event target to be like in the following way for example:
const elem = document.getElementById('foo'); elem.addEventListener('test', function (e) { console.log((e.target as HTMLInputElement).value); // 'bar' }, false); elem.dispatchEvent(new Event('test'));
In the code above we used a more specific type (i.e. HTMLInputElement
) because the value
property does not exist on the generic Element
type. The HTMLInputElement
type inherits from the Element
type though. Therefore, it will have the generic element properties (such as id
, class
, etc.) as well as the more specific ones that exclusively exist on the HTMLInputElement
object (such as value
, validity
, etc.).
Common Errors
Let's see a few more examples of some common errors associated with this issue:
Property 'files' does not exist on type 'EventTarget':
Assuming that the event target is <input type="file">
, we can fix this error like so:
// Property 'files' does not exist on type 'EventTarget'.
e.target.files;
// possible fix:
(e.target as HTMLInputElement).files;
Property 'controls' does not exist on type 'EventTarget':
Assuming that the event target is an HTML audio
/video
element, we can fix this error like so:
// Property 'controls' does not exist on type 'EventTarget'.
e.target.controls;
// possible fixes:
(e.target as HTMLMediaElement).controls;
(e.target as HTMLVideoElement).controls;
(e.target as HTMLAudioElement).controls;
Here, using the HTMLMediaElement
should be sufficient. However, we can also do the following when the target element can be either an audio
or a video
element:
type MediaType = HTMLVideoElement | HTMLAudioElement; (e.target as MediaType).form;
Property 'form' does not exist on type 'EventTarget':
Assuming that the event target is an HTML input
element, we can fix this error like so:
// Property 'form' does not exist on type 'EventTarget'.
e.target.form;
// possible fix:
(e.target as HTMLInputElement).form;
Assuming that the event target is an HTML textarea
element, we can fix this error like so:
// Property 'form' does not exist on type 'EventTarget'.
e.target.form;
// possible fix:
(e.target as HTMLTextAreaElement).form;
If the target element can be either an input
or a textarea
element, we can create a new intersection type like so:
// Property 'form' does not exist on type 'EventTarget'.
e.target.form;
// possible fix:
type InputType = HTMLInputElement | HTMLTextAreaElement;
(e.target as InputType).form;
Property 'checked' does not exist on type 'EventTarget':
Assuming that the event target is an HTML <input type="radio">
or <input type="checkbox">
element, we can fix this error like so:
// Property 'checked' does not exist on type 'EventTarget'.
e.target.checked;
// possible fix:
(e.target as HTMLInputElement).checked;
Property 'src' does not exist on type 'EventTarget':
Assuming that the event target is an HTML <img>
element, we can fix this error like so:
// Property 'src' does not exist on type 'EventTarget'.
e.target.src;
// possible fix:
(e.target as HTMLImageElement).src;
Assuming that the event target is an HTML <source>
element, we can fix this error like so:
// Property 'src' does not exist on type 'EventTarget'.
e.target.src;
// possible fix:
(e.target as HTMLSourceElement).src;
Property 'classList' does not exist on type 'EventTarget':
The classList
property exists on every HTML element, so we could use Element
, HTMLElement
or a more specific type (for e.g. HTMLInputElement
, etc.). For example:
// Property 'classList' does not exist on type 'EventTarget'.
e.target.classList;
// possible fixes:
(e.target as Element).classList;
(e.target as HTMLElement).classList;
// etc.
Property 'parentNode' does not exist on type 'EventTarget':
The parentNode
property exists on every HTML element, so we could use Element
, HTMLElement
or a more specific type (for e.g. HTMLInputElement
, etc.). For example:
// Property 'parentNode' does not exist on type 'EventTarget'.
e.target.parentNode;
// possible fixes:
(e.target as Element).parentNode;
(e.target as HTMLElement).parentNode;
// etc.
This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.