[typescript] The property 'value' does not exist on value of type 'HTMLElement'

I am playing around with typescript and am trying to create a script that will update a p-element as text is inputted in a input box.

The html looks as following:

<html>
    <head>
    </head>
    <body>
        <p id="greet"></p>
        <form>
            <input id="name" type="text" name="name" value="" onkeyup="greet('name')" />
        </form>
    </body>
    <script src="greeter.js"></script>
</html>

And the greeter.ts file:

function greeter(person)
{
    return "Hello, " + person;
}

function greet(elementId)
{
    var inputValue = document.getElementById(elementId).value;

    if (inputValue.trim() == "")
        inputValue = "World";

    document.getElementById("greet").innerText = greeter(inputValue);
}

When I compile with tsc I get the following "error":

/home/bjarkef/sandbox/greeter.ts(8,53): The property 'value' does not exist on value of type 'HTMLElement'

However the compiler does output a javascript file, which works just fine in chrome.

How come I get this error? And how can I fix it?

Also, where can I look up which properties are valid on a 'HTMLElement' according to typescript?

Please note I am very new to javascript and typescript, so I might be missing something obvious. :)

This question is related to typescript

The answer is


We could assert

const inputElement: HTMLInputElement = document.getElementById('greet')

Or with as-syntax

const inputElement = document.getElementById('greet') as HTMLInputElement

Giving

const inputValue = inputElement.value // now inferred to be string

If you have dynamic element ID where you need to assign the dynamic value, you may use this:

//element_id = you dynamic id.
//dynamic_val = you dynamic value.
let _el = document.getElementById(element_id);
_el.value = dynamic_val.toString();

This works for me.


The problem is here:

document.getElementById(elementId).value

You know that HTMLElement returned from getElementById() is actually an instance of HTMLInputElement inheriting from it because you are passing an ID of input element. Similarly in statically typed Java this won't compile:

public Object foo() {
  return 42;
}

foo().signum();

signum() is a method of Integer, but the compiler only knows the static type of foo(), which is Object. And Object doesn't have a signum() method.

But the compiler can't know that, it can only base on static types, not dynamic behaviour of your code. And as far as the compiler knows, the type of document.getElementById(elementId) expression does not have value property. Only input elements have value.

For a reference check HTMLElement and HTMLInputElement in MDN. I guess Typescript is more or less consistent with these.


If you are using react you can use the as operator.

let inputValue = (document.getElementById(elementId) as HTMLInputElement).value;

Try casting the element you want to update to HTMLInputElement. As stated in the other answers you need to hint to the compiler that this is a specific type of HTMLElement:

var inputElement = <HTMLInputElement>document.getElementById('greet');
inputElement.value = greeter(inputValue);

There is a way to achieve this without type assertion, by using generics instead, which are generally a bit nicer and safer to use.

Unfortunately, getElementById is not generic, but querySelector is:

const inputValue = document.querySelector<HTMLInputElement>('#greet')!.value;

Similarly, you can use querySelectorAll to select multiple elements and use generics so TS can understand that all selected elements are of a particular type:

const inputs = document.querySelectorAll<HTMLInputElement>('.my-input');

This will produce a NodeListOf<HTMLInputElement>.


Also for anyone using properties such as Props or Refs without your "DocgetId's" then you can:

("" as HTMLInputElement).value;

Where the inverted quotes is your props value so an example would be like so:

var val = (this.refs.newText as HTMLInputElement).value;
alert("Saving this:" + val);

If you are using angular you can use -

const element = document.getElementById('elemId') as HTMLInputElement;

Problem:

error Property 'text' does not exist on type 'HTMLElement'

Solution: in typeScript we need to cast document.getElementById() which returns type HTMLElement in < HTMLScriptElement >

So we can do it by by following way to resolve the error as expected by typescript.js

Code: var content: string = ( < HTMLScriptElement > document.getElementById(contentId)).text;

It worked for me.. hope it works for you as well.


A quick fix for this is use [ ] to select the attribute.

function greet(elementId) {
    var inputValue = document.getElementById(elementId)["value"];
    if(inputValue.trim() == "") {
        inputValue = "World";
    }
    document.getElementById("greet").innerText = greeter(inputValue);
}

I just try few methods and find out this solution,
I don't know what's the problem behind your original script.

For reference you may refer to Tomasz Nurkiewicz's post.


This work for me:

let inputValue = (swal.getPopup().querySelector('#inputValue ')as HTMLInputElement).value