134

I have an object X with a method getY() returning an object Y with a method a(), in typescript. What does it mean an expression like this one:

X.getY()!.a()

I guess the ! operator is used to check against null, but how does it work concretely? Where is defined in the language?

msanford
  • 11,803
  • 11
  • 66
  • 93
user2032922
  • 1,343
  • 2
  • 9
  • 6

2 Answers2

154

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 (!)

Eduard
  • 8,437
  • 10
  • 42
  • 64
Nitzan Tomer
  • 155,636
  • 47
  • 315
  • 299
  • 5
    wow. ive probably written `e && e.name` a couple thousand times. thanks – Tope Feb 05 '19 at 04:31
  • 55
    @Tope do not confuse this with a 'null safety operator' of other languages (a?.b?.c?.d?). This simply tells typescript compiler that a variable is not null, which may be false and it will crash at runtime – Daniel San Feb 05 '19 at 18:07
  • 4
    What would be a good use case for it? Because if I have to check for null anyway doesn't that beats the purpose? – StLia Oct 15 '19 at 16:03
  • 3
    @StLia What if you know for sure that something isn't null and you don't want/need to check for null? – Nitzan Tomer Oct 15 '19 at 21:13
  • A great use for it is during debugging when you know it isn't null and you want Typescript to not complain. – Steven T. Cramer Oct 17 '19 at 06:50
  • `e && e.name` equivalent to `e?.name` but if e is null during runtime and I used `e!.name` It will crash. Am I correct? – Rishav Apr 03 '20 at 08:16
  • 5
    @Rishav yes, you're right about the (javascript) optional chaining operator, and you're also correct about the (typescript) non-null assertion operator. but they also mean completely different things. The first says "i'm not sure, it can be null, but if not go ahead and..." but the later says "i'm 100% sure that it is not null". – Nitzan Tomer Apr 05 '20 at 08:39
  • For further information about the non null assertion operator, I also wrote an article which I recommend to see: [my article](https://medium.com/@emidomh/non-null-assertion-operator-a-typescript-feature-that-can-move-your-code-to-the-dark-side-ae6813a5270b) – Emidomenge Oct 18 '22 at 14:42
  • @Tope null safety operator does NOT tell the typescript compiler that a variable is not null. Furthermore it is called `Optional Chaining Operator` and -> accesses an object's property or calls a function. If the object accessed or function called using this operator is undefined or null, the expression short circuits and evaluates to undefined instead of throwing an error. – Youp Bernoulli May 25 '23 at 11:08
40

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.

Willem van der Veen
  • 33,665
  • 16
  • 190
  • 155