类型定义中的感叹号

Spa*_*ain 6 typescript angular

目前我偶然发现了 Angular的ContentChildren 装饰器。在第一个代码示例中,使用了以下语法:

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
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意在变量定义之后紧跟一个冒号感叹号@ContentChildren(ChildDirective) contentChildren。在此 StackOverflow 线程中,我发现在访问变量或对象属性时,此语法可用作“非空断言运算符”。

我现在的问题是类型定义之前的感叹号是否与正常上下文中的含义完全相同。它是简单地告诉 TypeScript 编译器:“好吧,不用担心null或未定义”,或者这种语法在这种情况下是否有其他特定含义?

luk*_*ter 21

我现在的问题是类型定义之前的感叹号是否与正常上下文中的含义完全相同。

不,这实际上不是一回事,在这种情况下,它做了不同的事情。通常,当您声明一个成员(不包含undefined在其类型中)时,它必须直接初始化或在构造函数中初始化。如果您!在名称后添加,TypeScript 将忽略它,并且如果您不立即对其进行初始化,则不会显示错误:

class Foo {
  foo: string; // error: Property 'foo' has no initializer and is not definitely assigned in the constructor.
  bar!: string; // no error
}
Run Code Online (Sandbox Code Playgroud)

同样的事情实际上也适用于局部变量:

let foo: string;
let bar!: string;

console.log(foo); // error: Variable 'foo' is used before being assigned.
console.log(bar); // no error
Run Code Online (Sandbox Code Playgroud)

操场

  • 该功能是在 TS2.7 中添加的。相关文档:[带有`!`的明确赋值断言](http://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#definite-assignment-assertions) (3认同)