52

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.

6
  • 3
    This: (myRow.querySelector('.myClass') as HTMLInputElement).value = myVal doesn't work? Commented Mar 26, 2017 at 17:18
  • Correct. That yields the error: '2349: Cannot invoke an express whose type lacks a call signature.' Commented Mar 26, 2017 at 17:36
  • What is myRow? Commented Mar 26, 2017 at 22:04
  • 1
    For the purpose of this question, any HTML element. The result of querySelector is an HTMLInputElement. Commented Mar 26, 2017 at 22:48
  • Can you post a link to a playground that demonstrates this scenario? Commented Mar 26, 2017 at 22:54

4 Answers 4

92

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
Sign up to request clarification or add additional context in comments.

14 Comments

Thanks; that works. Nailed it on the semicolon. Do you know why that's required?
Per this page: github.com/rse/es6-features, "Both ECMAScript 6 and all tools (including compressors) perfectly support automatic semicolon inference/insertion nowadays. As a consequence, ECMAScript 6 coders nowadays can get rid of nearly all semicolons and remove clutter from their source code." Ie, it's weird to require a semicolon in this specific case.
"...get rid of nearly all semicolons". In your case it makes a difference
Do I always have to cast when I use this element? What if I'm quite sure that this element exists on my page. Can I already specify its type when I first declare and query it.
|
2

The other answers here did not help. I found elsewhere and via trial and error that

  1. querySelector is an HTMLElement
  2. querySelectorAll is an array of them HTMLElement[]
sections: HTMLElement[] = [];

this.sections = someElement.nativeElement.querySelectorAll('li') as HTMLElement[];

Comments

2

I did it like this:

const myClass: HTMLInputElement | null = document.querySelector(".my-class") as HTMLInputElement;

if (myClass) {
    myClass.value = myVal;
}

Comments

0
//  define
export const $ = <T>(selector, scope = document): T =>
  scope.querySelector(selector);


//  use
const $account: HTMLInputElement = $("#login-account");

// example tips for  .value
const account = $account.value

1 Comment

While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. You can find more information on how to write good answers in the help center: stackoverflow.com/help/how-to-answer . Good luck 🙂

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.