Exclamation Mark in type definition

2020-04-19 18:38发布

问题:

Currently I stumbled upon the ContentChildren decorator of Angular. In the first code example the following syntax is used:

import {AfterContentInit, ContentChildren, Directive, QueryList} from '@angular/core';

@Directive({selector: 'child-directive'})
class ChildDirective {
}

@Directive({selector: 'someDir'})
class SomeDir implements AfterContentInit {
  @ContentChildren(ChildDirective) contentChildren !: QueryList<ChildDirective>;  // this line is relevant

  ngAfterContentInit() {
    // contentChildren is set
  }
}

Note the exclamation mark followed by a colon right after the @ContentChildren(ChildDirective) contentChildren variable definition. In this StackOverflow thread I discovered that this syntax can be used as a "non-null assertion operator" when accessing a variable or object property.

My question is now whether the exclamation mark before a type definition has exactly the same meaning like in a normal context. Does it simply say the TypeScript compiler: "Okay, don't worry about null or undefined", or does this syntax have another specific meaning in this context?

回答1:

My question is now whether the exclamation mark before a type definition has exactly the same meaning like in a normal context.

No that's actually not the same thing, in this context it does something different. Normally when you declare a member (which doesnt' include undefined in it's type) it has to be initialized directly or in the constructor. If you add ! after the name, TypeScript will ignore this and not show an error if you don't immediately initialize it:

class Foo {
  foo: string; // error: Property 'foo' has no initializer and is not definitely assigned in the constructor.
  bar!: string; // no error
}

The same thing actually applies to local variables as well:

let foo: string;
let bar!: string;

console.log(foo); // error: Variable 'foo' is used before being assigned.
console.log(bar); // no error

Playground