Fix - Type 'HTMLElement or null' is not assignable to type

avatar

Borislav Hadzhiev

Thu Mar 31 20223 min read

banner

Photo by Brooke Cagle

Fix - Type 'HTMLElement or null' is not assignable to type #

The "Type 'HTMLElement | null' is not assignable to type" error occurs when a possibly null value is assigned to something that expects an element. To solve the error, use a non-null assertion or a type guard to verify the value is a an element before the assignment.

htmlelement or null not assignable type

This is the html code for the examples in this article.

index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> </head> <body> <input id="submit" type="submit" name="submit" /> <script src="./src/index.ts"></script> </body> </html>

And here are 3 examples of how the error occurs.

src/index.ts
// 👇️ const input: HTMLElement | null const input = document.getElementById('submit'); // ⛔️ Type 'HTMLElement | null' is not assignable to type 'HTMLElement'. // Type 'null' is not assignable to type 'HTMLElement'.ts(2322) const el1: HTMLElement = input; // --------------------------------------- // ⛔️ Type 'HTMLElement | null' is not assignable to type 'Element'. // Type 'null' is not assignable to type 'Element'.ts(2322) const el2: Element = input; // --------------------------------------- function example(el: Element) { return el; } // ⛔️ Argument of type 'HTMLElement | null' is not assignable // to parameter of type 'Element'. // Type 'null' is not assignable to type 'Element'.ts(2345) example(input);

The input variable has a type of HTMLElement | null.

The el1 and el2 variables have a type of HTMLElement and Element, so they only expect to get assigned a value of that type.

TypeScript is basically telling us that the input variable might have a value of null, which is not compatible with the type of the el1 variable, which only expects an HTMLElement.

Here are a couple of examples of how you can solve the error.

src/index.ts
// 👇️ const input: HTMLElement | null const input = document.getElementById('submit'); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const el1: HTMLElement = input!; // 👈️ non-null assertion // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const el2: Element = input!; // 👈️ non-null assertion function example(el: Element) { return el; } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion example(input!); // 👈️ non-null assertion

The exclamation mark is the non-null assertion operator in TypeScript.

It removes null and undefined from a type without doing any explicit type checking.

When you use this approach, you basically tell TypeScript that this value will never be null or undefined.

This is very similar to a type assertion and should only be used when you're absolutely sure that the value is of the expected type.

src/index.ts
const input = document.getElementById('submit'); const el1: HTMLElement = input as HTMLElement; // 👈️ type assertion const el2: Element = input as Element; // 👈️ type assertion function example(el: Element) { return el; } example(input as HTMLElement); // 👈️ type assertion

Type assertions are used when we have information about the type of a value that TypeScript can't know about.

We effectively tell TypeScript that el1 will be an HTMLElement and not to worry about it.

You can also use a type assertion directly when selecting the element.

src/index.ts
// 👇️ used type assertion here const input = document.getElementById('submit') as HTMLInputElement; const el1: HTMLElement = input; const el2: Element = input; function example(el: Element) { return el; } example(input);

We typed the input element as HTMLInputElement effectively removing null from its type.

The types are consistently named as HTML***Element. Once you start typing HTML.., your IDE should be able to help you with autocomplete.

Some commonly used types are: HTMLInputElement, HTMLButtonElement, HTMLAnchorElement, HTMLImageElement , HTMLDivElement, HTMLTextAreaElement, etc.

An alternative, and much better approach is to use a type guard.

src/index.ts
// 👇️ const input: HTMLElement | null const input = document.getElementById('submit'); function example(el: Element) { return el; } if (input != null) { const el1: HTMLElement = input; const el2: Element = input; example(input); }

The if statement serves as a type guard. We explicitly check if the input variable does not store a null value.

src/index.ts
// 👇️ const input: HTMLElement | null const input = document.getElementById('submit'); // 👉️ input has type HTMLElement or null here if (input != null) { // 👉️ input has type HTMLElement here const el1: HTMLElement = input; const el2: Element = input; example(input); } function example(el: Element) { return el; }

TypeScript knows that the input variable has a type of HTMLElement in the if block and allows us to directly assign it to the el1 and el2 variables.

Use the search field on my Home Page to filter through my more than 1,000 articles.