31
votes

Is there a way to make TypeScript not throw the error 'TS2339: property value does not exist on type Element' for code like this:

myRow.querySelector('.my-class').value = myVal

Casting as < HTMLInputElement > Causes the code to break entirely.

Typescript seems to not handle things involving the DOM well in general, unless I'm missing something; ie it chooses specific over general for functions that could return any element.

1
This: (myRow.querySelector('.myClass') as HTMLInputElement).value = myVal doesn't work? - Nitzan Tomer
Correct. That yields the error: '2349: Cannot invoke an express whose type lacks a call signature.' - Turtles Are Cute
What is myRow? - Nitzan Tomer
For the purpose of this question, any HTML element. The result of querySelector is an HTMLInputElement. - Turtles Are Cute
Can you post a link to a playground that demonstrates this scenario? - Nitzan Tomer

1 Answers

56
votes

The querySelector method returns Element | null.
If you're not using strictNullChecks then Element, and it doesn't have the value member.

And so casting it to HTMLInputElement as I wrote in my comment works:

let myRow = document.getElementById('my-row');
(myRow.querySelector('.myClass') as HTMLInputElement).value = " a vaule";

The error you are receiving is a result of forgetting the semicolon at the end of the first line, what happens is that the compiler thinks that you're trying to do this:

document.getElementById('my-row')(myRow.querySelector('.myClass') as HTMLInputElement)

Don't forget to end lines with semicolons.


Edit

The querySelector method is generic so you can also do:

document.getElementById('my-row').querySelector<HTMLInputElement>('.myClass').value

And in case of strictNullChecks if you're sure the element is there you can use the Non-null assertion operator:

document.getElementById('my-row')!.querySelector<HTMLInputElement>('.myClass')!.value