I guess you misunderstood what a type assertion does. It's not something that compiler ensures, it's a kind of "waiver" you give the compiler saying "I hereby renounce the right to have this type checked, I guarantee that it will be X at run-time and I'm responsible for consequences if it is not".

By using the ! assertion you're basically telling the compiler "shut up, I know better, this never gonna be null". The compiler has no option but to agree with you, but if you don't keep your promise (which you don't), a run time fault is imminent.

Obviously, a type assertion is almost never a good idea. Finally, the whole point of Typescript is to have your types statically checked. Think twice before putting ! or as here and there.

Answer from georg on Stack Overflow
🌐
TypeScript
typescriptlang.org › docs › handbook › release-notes › typescript-2-0.html
TypeScript: Documentation - TypeScript 2.0
Specifically, the operation x! produces a value of the type of x with null and undefined excluded. Similar to type assertions of the forms <T>x and x as T, the ! non-null assertion operator is simply removed in the emitted JavaScript code.
Top answer
1 of 3
170

It's called the "Non-null assertion operator" and it tells the compiler that x.getY() is not null.

It's a new typescript 2.0 feature and you can read about it in the what's new page, here's what it says:

A new ! post-fix expression operator may be used to assert that its operand is non-null and non-undefined in contexts where the type checker is unable to conclude that fact. Specifically, the operation x! produces a value of the type of x with null and undefined excluded. Similar to type assertions of the forms x and x as T, the ! non-null assertion operator is simply removed in the emitted JavaScript code.

// Compiled with --strictNullChecks
function validateEntity(e?: Entity) {
    // Throw exception if e is null or invalid entity
}

function processEntity(e?: Entity) {
    validateEntity(e);
    let s = e!.name;  // Assert that e is non-null and access name
}

Edit

There's an issue for documenting this feature: Document non-null assertion operator (!)

2 of 3
45

Non-null assertion operator: !

  • You tells the TS compiler that the value of a variable is not null | undefined
  • Use it when you are in possession of knowledge that the TS compiler lacks.

Here is a trivial example of what it does:

let nullable1: null | number;
let nullable2: undefined | string;

let foo  = nullable1! // type foo: number
let fooz = nullable2! // type fooz: string

It basically removes null | undefined from the type


When do I use this?

Typescript is already pretty good at inferring types for example using typeguards:

let nullable: null | number | undefined;

if (nullable) {
    const foo = nullable; // ts can infer that foo: number, since if statements checks this
}

However sometimes we are in a scenario which looks like the following:

type Nullable = null | number | undefined;

let nullable: Nullable;

validate(nullable);

// Here we say to ts compiler:
// I, the programmer have checked this and foo is not null or undefined
const foo = nullable!;  // foo: number

function validate(arg: Nullable) {
    // normally usually more complex validation logic
    // but now for an example
    if (!arg) {
        throw Error('validation failed')
    }
}

My personal advice is to try to avoid this operator whenever possible. Let the compiler do the job of statically checking your code. However there are scenarios especially with vendor code where using this operator is unavoidable.

🌐
Biome
biomejs.dev › linter › rules › no-non-null-assertion
noNonNullAssertion | Biome
code-block.ts:5:21 lint/style/noNonNullAssertion FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ⚠ Forbidden non-null assertion. 3 │ } 4 │ declare const foo: Example; > 5 │ const includesBaz = foo.property!.includes(‘baz’); │ ^^^^^^^^^^^^^ 6 │ ℹ Unsafe fix: Replace with optional chain operator ?.
🌐
GeeksforGeeks
geeksforgeeks.org › typescript › typescript-non-null-assertion-operator-postfix-type
TypeScript Non-null Assertion Operator (Postfix !) Type - GeeksforGeeks
April 28, 2025 - Inside the function, we use the non-null assertion operator name! to assert that the name is not null or undefined. We then use formattedName to hold the non-null value of the name, allowing us to treat it as a string.
🌐
Sentry
sentry.io › sentry answers › react › how to fix the forbidden non-null assertion in typescript and react?
How to fix the forbidden non-null assertion in TypeScript and React? | Sentry
The Non-null Assertion Operator (Postfix !) assertion removes the null and undefined types from a value. To use it, add the ! symbol after an expression like in the console log example above.
🌐
TypeScript ESlint
typescript-eslint.io › rules › no-non-null-assertion
no-non-null-assertion | typescript-eslint
TypeScript's ! non-null assertion operator asserts to the type system that an expression is non-nullable, as in not null or undefined. Using assertions to tell the type system new information is often a sign that code is not fully type-safe.
Find elsewhere
🌐
SonarSource
rules.sonarsource.com › typescript › rspec-2966
Non-null assertions should not be used
Unique rules to find Bugs, Vulnerabilities, Security Hotspots, and Code Smells in your TYPESCRIPT code
🌐
GitHub
github.com › microsoft › TypeScript › issues › 50304
Have non-null assertion operator (!) compile to an assertion in Javascript · Issue #50304 · microsoft/TypeScript
May 20, 2022 - Non-null assertion is used when you want to indicate that due to the business logic, a given value should not be null (and if it is, that constitutes an error that needs to be immediately observed).
Published   Aug 15, 2022
🌐
Stack Overflow
stackoverflow.com › questions › 76232881 › how-to-get-rid-of-non-null-assertion
typescript - How to get rid of non-null assertion - Stack Overflow
function greet(name: string | null): string { // Use the non-null assertion operator to assert that 'name' is not null return `Hello, ${name!.toUpperCase()}!`; } console.log(greet("Alice")); // Output: Hello, ALICE!
🌐
DEV Community
dev.to › this-is-learning › typescript-tips-tricks-non-null-assertion-operator-21eb
Typescript - Tips & Tricks - Non-null assertion operator - DEV Community
September 9, 2021 - You can assert that a property exists, but then when you reference it on the next line, typescript is unable to infer from the control statement that myObj is not null. I come across these issues all the time. I didn't realise this feature existed and I highly expect I'll need to use it at some point before the week is out. ... @Google Developer Expert, Former Microsoft MVP, @GitKraken Ambassador, Senior Software Developer and JavaScript enthusiastic Youtube Channel https://youtube.com/@Puppo_92
Top answer
1 of 3
12

After looking at the documentation, this can be accomplished using inline casting. So in your case, the correct code should be like this:

// @ts-check

const element = /** @type {HTMLInputElement} */ (document.getElementById('checkbox'));

Also, make sure that after the /** @type {...} */ annotation you need to wrap your code using parentheses.

2 of 3
6

Here's a better way so you don't have to always write out the exact type of the value, more like the convenience of the non-null operator in TS:

/**
 * In lieu of writing in TypeScript and having the convenient non-null assertion
 * operator (!), this helper function allows asserting that something is not
 * null or undefined without having to write a JSDoc type cast that has to
 * explicitly know the non-null type (which is error prone).
 *
 * For example, insgtead of having to write this:
 *
 * ```js
 * const value = /** @​type {SomeNullableType} *​/(possiblyNullValue)
 * ```
 *
 * we can write this:
 *
 * ```js
 * const value = NonNull(possiblyNullValue)
 * ```
 *
 * @template {any} T
 * @param {T} item
 */
function NonNull(item) {
    if (item === null || item === undefined) throw 'item is null or undefined'
    return item
}

In this example, the type of div will be HTMLDivElement, not HTMLDivElement | null, as desired (plus it will throw if you are actually wrong, which may be even more desirable!):

const div = NonNull(document.querySelector('div'))

Screenshot of the type awareness in VS Code with and without using NonNull:

You could also do this, which will not do a runtime check, but will force it to be non-nullable (more like the non-null ! operator):

/**
 * @template {any} T
 * @param {T} item - Item you want to strip nullable from.
 * @returns {NonNullable<T>}
 */
function NonNull(item) {
  return /** @type {NonNullable<T>} */(item)
}

/** @type {number | null} */
const foo = 123

// type of `test` is `number`
const test = NonNull(foo)

Words of advice

Go for the one that has the conditional check. The second one, that does a type cast, can result in undefined silently flowing through your program without any runtime error, manifesting in the wrong outcomes (f.e. something different is rendered on screen, your server sends back something else to a client, or etcetera).

If you expect something to not be null, it is safer to actually expect that in your code.

If you think the conditional check is going to ruin your performance (and that the difference will actually matter), you may be wrong. Don't give up a good thing unless something significantly worse actually exists and giving up the good thing to solve it is actually worth it.

🌐
Learn TypeScript
learntypescript.dev › 07 › l2-non-null-assertion-operator
Using the non-null assertion operator | Learn TypeScript
The non-null assertion operator is an exclamation mark (!), and this is placed after the variable or expression that we want to tell TypeScript isn't null or undefined.
🌐
Medium
medium.com › @raindefiance › ts-operators-16d8c70047bb
TS operators. Non-null assertion operator (!) | by Tech Beast | Medium
August 21, 2024 - Specifically, the operation x! produces a value of the type of x with null and undefined excluded. Similar to type assertions of the forms <T>x and x as T, the ! non-null assertion operator is simply removed in the emitted JavaScript code.
🌐
GitHub
github.com › microsoft › TypeScript › issues › 9637
Remove the non-null assertion operator · Issue #9637 · microsoft/TypeScript
July 12, 2016 - function validateEntity(e: Entity?): e is Entity { if (e == null) { throw new Error(); } return true; } function processEntity(e: Entity?) { if (validateEntity(e)) { let s = e.name; // Guard asserts e is an Entity (and therefore non-null) and access name } }
Published   Jul 12, 2016
🌐
Klocwork
help.klocwork.com › 2025.1 › en-us › reference › js.ts.no.confusing.non.null.assertion.htm
JS.TS.NO.CONFUSING.NON.NULL.ASSERTION
a! == b; // a non-null assertions(`!`) and an equals test(`==`) a !== b; // not equals test(`!==`) a!