首页 > 解决方案 > 类属性中的非空断言

问题描述

我对打字稿相当陌生,并且已经在网上搜索试图找到对此的解释。

最近我一直在做一个项目,并想用它来续集。在阅读文档的打字稿部分时,我遇到了以下示例:

// These are all the attributes in the User model
interface UserAttributes {
  id: number;
  name: string;
  preferredName: string | null;
}

// Some attributes are optional in `User.build` and `User.create` calls
interface UserCreationAttributes extends Optional<UserAttributes, "id"> {}

class User extends Model<UserAttributes, UserCreationAttributes>
  implements UserAttributes {
  public id!: number; // Note that the `null assertion` `!` is required in strict mode.
  public name!: string;
  public preferredName!: string | null; // for nullable fields

  // timestamps!
  public readonly createdAt!: Date;
  public readonly updatedAt!: Date;

  //other code
}

在类内部,preferredName也有非空断言运算符,但随后继续在其类型中包含 null。

这是否会覆盖静态类型检查,因为它可能在运行时为空(即用户没有首选名称)?

或者有没有更好的解释为什么他们会在该属性上包含非空运算符?比如排除未定义但包含null。

标签: typescriptsequelize-typescript

解决方案


这主要是一个术语问题:

  • null并且undefined是不同的,即使语言的某些部分以类似方式对待它们。(例如,非空断言运算符null从它所操作的表达式的域中消除两者undefined。)

  • !属性声明之后是明确赋值断言运算符运算符,而不是非空断言运算符。(它们都是用后缀编写的!,但是一个非空断言出现在一个表达式之后,而一个明确的赋值断言出现在一个变量/属性声明之后。)一个明确的赋值断言告诉编译器它不需要验证一个变量或属性在使用前已经初始化。明确赋值断言运算符与 . 无关null

如果您不初始化属性或变量,则如果您从中读取,它的值将是undefined,而不是。null如果您启用--strictPropertyInitialization编译器选项--strict(或仅包含它),并且您有一个类型不包含undefined(not null)的类属性,那么您必须在声明时立即初始化它,在构造函数中无条件初始化它,或者使用一个明确的赋值断言:

class Example {
    a: string | undefined; // okay: includes undefined
    b: string | null = "b"; // okay: initialized
    c: string | null; // okay: assigned in constructor
    d: string | null; // error: compiler cannot be sure it is assigned
    e!: string | null; // okay: asserted as assigned

    constructor() {
        this.c = "c";
        if (Math.random() < 1000) {
            this.d = "d"
            this.e = "e";
        }
    }
}

Playground 代码链接


推荐阅读