Borislav Hadzhiev
Thu Mar 24 2022·2 min read
Photo by Darren Lawrence
The error "Property 'click' does not exist on type 'Element'" occurs when we
try to call the click()
method on an element that has a type of Element
. To
solve the error, use a type assertion to type the element as HTMLElement
before calling the method.
This is the index.html
file for the examples in this article.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> </head> <body> <button id="btn">Submit</button> <script src="./src/index.ts"></script> </body> </html>
And here is an example of how the error occurs in the index.ts
file.
// 👇️ const btn: Element | null const btn = document.querySelector('#btn'); btn?.addEventListener('click', () => { console.log('button clicked'); }); if (btn != null) { // ⛔️ Property 'click' does not exist on type 'Element'.ts(2339) btn.click(); }
The reason we got the error is because the return type of the
document.querySelector
method is Element | null
and the
click
method doesn't exist on the Element
type.
To solve the error, use a type assertion to type the element as an
HTMLElement
.
const btn = document.querySelector('#btn') as HTMLElement | null; btn?.addEventListener('click', () => { console.log('button clicked'); }); if (btn != null) { btn.click(); }
If you used the
document.getElementsByClassName
method, type the collection as HTMLCollectionOf<HTMLElement>
.
// 👇️ with getElementsByClassName // type as HTMLCollectionOf<HTMLElement> const btns = document.getElementsByClassName( 'btn', ) as HTMLCollectionOf<HTMLElement>; for (let i = 0; i < btns.length; i++) { btns[i].click(); }
We used the HTMLElement
type in the example above, however we could have also
used the HTMLButtonElement
type to be more specific.
Type assertions are used when we have information about the type of a value that TypeScript can't know about.
btn
variable stores anHTMLElement
or a null
value and not to worry about it.We used a
union type
to specify that the variable could still be null
, because if an HTML element
with the provided selector does not exist in the DOM, the querySelector()
method returns a null
value.
We used a simple if
statement that serves as a
type guard
to make sure the btn
variable doesn't store a null
value before calling its
click()
method.
const btn = document.querySelector('#btn') as HTMLElement | null; btn?.addEventListener('click', () => { console.log('button clicked'); }); // 👉️ btn has type HTMLElement or null here if (btn != null) { // 👉️ btn has type HTMLElement here btn.click(); }
btn
variable has a type of HTMLElement
in the if
block and allows us to directly call its click()
method.It's always a best practice to include null
in the type assertion, because the
querySelector
method would return null
if no element with the provided
selector was found.
You might also use the
optional chaining (?.)
operator to short-circuit if the reference is equal to null
or undefined
const btn = document.querySelector('#btn') as HTMLElement | null; // 👇️ using optional chaining (?.) btn?.addEventListener('click', () => { console.log('button clicked'); }); // 👇️ using optional chaining (?.) btn?.click();
The optional chaining operator short-circuits returning undefined
if the
reference is equal to null
or undefined
.
In other words, if the btn
variable stores a null
value, we won't attempt to
call the click()
method on null
and get a runtime error.