Borislav Hadzhiev
Mon Mar 21 2022·2 min read
Photo by Hannah Dickens
The error "Property 'X' does not exist on type 'HTMLElement'" occurs when we
try to access a property that doesn't exist on an element of type HTMLElement
.
To solve the error, use a type assertion to type the element correctly before
accessing the property.
This is the index.html
file for the examples in this article.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> </head> <body> <input id="first_name" type="text" name="first_name" value="Initial Value" /> <a id="link" href="https://google.com" target="_blank">Open Google</a> <button id="btn">Submit</button> <script src="./src/index.ts"></script> </body> </html>
And here are 3 examples of how the error occurs in the index.ts
file.
const input = document.getElementById('input'); if (input != null) { // ⛔️ Property 'value' does not exist on type 'HTMLElement'.ts(2339) const value = input.value; console.log(value); } // --------------------------- const link = document.getElementById('link'); if (link != null) { // ⛔️ Property 'href' does not exist on type 'HTMLElement'.ts(2339) const href = link.href; console.log(href); } // --------------------------- const btn = document.getElementById('btn'); if (btn != null) { // ⛔️ Property 'disabled' does not exist on type 'HTMLElement'.ts(2339) btn.disabled = true; }
The reason we got the error is because the return type of the
document.getElementById
method is HTMLElement | null
and the properties we tried to access don't exist
on the HTMLElement
type.
To solve the error, use a type assertion to type the element correctly, e.g. as
HTMLInputElement
, HTMLButtonElement
, HTMLAnchorElement
, HTMLImageElement
, HTMLTextAreaElement
, etc - depending on the type of element you are working
with.
The types are consistently named as HTML***Element
. Once you start typing
HTML..
, your IDE should be able to help you with autocomplete.
const input = document.getElementById('input') as HTMLInputElement | null; if (input != null) { const value = input.value; console.log(value); } // --------------------------- const link = document.getElementById('link') as HTMLAnchorElement | null; if (link != null) { const href = link.href; console.log(href); } // --------------------------- const btn = document.getElementById('btn') as HTMLButtonElement | null; if (btn != null) { btn.disabled = true; }
Type assertions are used when we have information about the type of a value that TypeScript can't know about.
input
variable stores anHTMLInputElement
or a null
value and not to worry about it.Similarly, we typed the link
variable to be an HTMLAnchorElement
or null
and the btn
variable - HTMLButtonElement
or null
.
We used a
union type
to specify that the variable could still be null
, because if an HTML element
with the provided id
does not exist in the DOM, the getElementById()
method
returns a null
value.
We used a simple if
statement that serves as a
type guard
to make sure the input
variable doesn't store a null
value before accessing
its value
property.
const input = document.getElementById('input') as HTMLInputElement | null; // 👉️ input has type HTMLInputElement or null here if (input != null) { // 👉️ input has type HTMLInputElement here const value = input.value; console.log(value); }
input
variable has a type of HTMLInputElement
in the if
block and allows us to directly access its value
property.It's always a best practice to include null
in the type assertion, because the
getElementById
method would return null
if no element with the provided id
was found.