类型定义中的感叹号

Posted

技术标签:

【中文标题】类型定义中的感叹号【英文标题】:Exclamation Mark in type definition 【发布时间】:2020-01-09 00:44:29 【问题描述】:

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

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
  

注意@ContentChildren(ChildDirective) contentChildren 变量定义后面的感叹号和冒号。在this *** thread 中,我发现在访问变量或对象属性时,这种语法可以用作“非空断言运算符”。

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

【问题讨论】:

【参考方案1】:

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

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

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

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

let foo: string;
let bar!: string;

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

Playground

【讨论】:

此功能是在 TS2.7 中添加的。相关文档:definite assignment assertions with !

以上是关于类型定义中的感叹号的主要内容,如果未能解决你的问题,请参考以下文章

c语言中如何将结构中变量清空

excel重感叹号(!)是啥意思

Swift 类型推断需要问号或感叹号

Dart 中的函数类型定义/函数类型别名是啥?

包定义中的 Oracle 用户定义类型

与JAVA类型相比较,MapReduce中定义的数据类型都有哪些特点?