6
votes
var out = document.getElementsByClassName('myclass')[0];
out.focus();
out.select();
out.selectionStart =1;

I'm trying to do this in my typescript file, but for some reason it gives me these errors

ERROR in src/app/main/utilities/keyboard/keyboard.component.ts(29,9): error TS2339: Property 'focus' does not exist on type 'Element'. src/app/main/utilities/keyboard/keyboard.component.ts(30,9): error TS2339: Property 'select' does not exist on type 'Element'. src/app/main/utilities/keyboard/keyboard.component.ts(31,9): error TS2339: Property 'selectionStart' does not exist on type 'Element'.

It is saying that the property does not exist, but it does. When I run this, everything works as it should but I have to do with a huge block of red text in my console which is annoying.

2
What type of element is it?Ryan Cavanaugh
its an Input elementEric Chu
You just need to cast the object to a type that has the properties you want to call (i.e. the actual type the object it). Typescript can only do compile-time type checking, and still generates javascript that will work if the run-time object does have the property or method.crashmstr

2 Answers

11
votes

You need to type cast your out variable to an HtmlElement in order for Typescript to know what methods and properties are available.

var out = document.getElementsByClassName('myclass')[0] as HtmlElement;

You can also do something like this:

(out as HtmlElement).focus();

Or this:

(<HtmlElement>out).focus();

But then you'll have to re-assert the type every time you use out.

Read more about type casting / type assertions here: https://www.typescriptlang.org/docs/handbook/basic-types.html

3
votes

The compiler doesn't know that the Element you are looking at is an HTMLInputElement, so it warns you. If you are positive you are getting an HTMLInputElement, then you can use an assertion like @vincecampanale suggests. Or, you can do something to convince the compiler, like using a user-defined type guard to check:

function isHTMLInputElement(x: Element): x is HTMLInputElement {
  return (x.tagName.toUpperCase() === 'INPUT');
}

var out = document.getElementsByClassName('myclass')[0];

// check that out is really an input element
if (!isHTMLInputElement(out)) 
  throw new Error("My life is a lie");

// from here on out, the compiler is convinced that out is an input element
out.focus(); // okay
out.select(); // okay
out.selectionStart = 1; // okay

The compiler is happy with the above code, because it uses control flow analysis to recognize that the code at and after out.focus() will only run if the type of out is HTMLInputElement. Note that this does not suffer from the issue where you have to keep re-asserting that out is an HTMLInputElement.

Hope that helps.