The property ‘value’ does not exist on value of type ‘HTMLElement’

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:






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. 🙂

Solutions/Answers:

Solution 1:

Based on Tomasz Nurkiewiczs answer, the “problem” is that typescript is typesafe. 🙂 So the document.getElementById() returns the type HTMLElement which does not contain a value property. The subtype HTMLInputElement does however contain the value property.

Related:  How to check for an undefined or null variable in JavaScript?

So a solution is to cast the result of getElementById() to HTMLInputElement like this:

var inputValue = (<HTMLInputElement>document.getElementById(elementId)).value;

<> is the casting operator in typescript. See the question TypeScript: casting HTMLElement.

The resulting javascript from the line above looks like this:

inputValue = (document.getElementById(elementId)).value;

i.e. containing no type information.

Solution 2:

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

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

Solution 3:

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);

Solution 4:

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.

Related:  Comet and jQuery [closed]

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.

Solution 5:

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.

Solution 6:

Updated example:

const inputElement: HTMLInputElement = document.getElementById('greet') as HTMLInputElement
const inputValue: string = InputElement.value

Documentation:

TypeScript – Basic Types – Type assertions