【问题标题】:Non-null assertion in class property类属性中的非空断言
【发布时间】:2021-04-28 23:42:32
【问题描述】:

我对 typescript 还很陌生,并且已经在网上搜索过,试图找到对此的解释。

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

// 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。

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

或者是否有更好的解释来解释为什么它们会在该属性上包含非空运算符?比如排除undefined但包含null。

【问题讨论】:

  • 对我来说,它看起来只是为了保持一致性,或者是使用自动化工具创建的,或者它表明虽然它没有在构造函数中初始化,但它实际上在创建时被赋予了正确的模型值。我怀疑这是否意味着preferredName 不为空

标签: typescript sequelize-typescript


【解决方案1】:

这主要是一个术语问题:

  • nullundefined 是不同的,尽管语言的某些部分以类似方式对待它们。 (例如,non-null assertion operatornullundefined 从它所操作的表达式的域中删除。)

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

如果你不初始化一个属性或变量,它的值将是undefined,而不是null,如果你从中读取的话。如果您启用了the --strictPropertyInitialization compiler option(或者只是--strict,其中包括它),并且您有一个类型不包括undefined(不是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 link to code

【讨论】:

    猜你喜欢
    • 2016-06-21
    • 2021-12-16
    • 2022-11-22
    • 1970-01-01
    • 2014-09-05
    • 2018-11-22
    • 2016-05-12
    • 1970-01-01
    • 2018-09-21
    相关资源
    最近更新 更多