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 (!)
Answer from Nitzan Tomer on Stack OverflowVideos
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 (!)
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.
In my Express server, I have the situation that certain request properties are guaranteed by middleware, but the compiler doesn't know.
Hence, req.user could be "possibly undefined" even though I have middleware that checks for it before every request:
Lint doesn't like the ! operator to assert non-nullishness. But it doesn't complain when using as:
My question here: Are there any actual benefits of using the as operator here? Or is it effectively exactly the same?
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.
If you run compilation with --strictNullChecks, a compilation error
error TS2531: Object is possibly 'null'.
should be raised. I guess the author intended to state that non-null assertions lead to runtime exception if you continue to use the object that supposedly is non-null.
For example calling a function on taxValue in your example above with the non-null assertion would not warn you that the value might be null but if it is null and you call the function during runtime it will raise an exception.
The non-null assertion can be used for you to remove falsy warning that a knonw-non-null variable whose type could be null can be used as if it were not nullable.