【问题标题】:How to fix "Property has no initializer and is not definitely assigned in the constructor" error?如何修复“属性没有初始化程序并且未在构造函数中明确分配”错误?
【发布时间】:2021-03-09 20:57:54
【问题描述】:

我对这些课程有疑问。我想使用doSomething()B 独有的方法而不每次都进行类型转换,但是当我将属性a 指定为B 类型时,它告诉我它没有在构造函数中分配,这有点错误,因为父构造函数进行了赋值。

class A {

}

class B extends A {
  doSomething() { }
}

class One {
  constructor(protected a: A){  }
}

class Two extends One {
  protected a: B // Property 'a' has no initializer and is not definitely assigned in the constructor.

  constructor(){
    super(new B());
    // If I enter "this.a = new B();" here then the error disappears, but the code is redundant.
  }

  doStuff() {
    this.a.doSomething()
  }
}

我做错了什么?

Playground

【问题讨论】:

  • 您说父类构造函数进行赋值,但在您提供的代码中,父类构造函数中没有发生赋值。哪一个是真的?附:请不要添加不相关的标签。
  • 在打字稿中,constructor(protected a: A){ } 是 constructor (a: A) { this.a = a; 的简写。 }
  • 是的,但是你为什么期望它在严格模式下不会出错(我知道发出的代码是constructor(a) { this.a = a; })呢?除了 jcalz 的回答之外,您还可以使用 definite assignment assertions,这似乎是一个 good case

标签: typescript typescript-class


【解决方案1】:

问题在于,将class field declarations 添加到 JavaScript 的提议与您可能期望的语义以及 TypeScript 设计人员在将它们添加到 TypeScript 时所期望的语义不同。事实证明,在 JavaScript 中,类字段声明将通过 Object.defineProperty() 而不是通过赋值来初始化,并且所有没有初始化器的声明字段都将使用 undefined 初始化。因此,最终您可以期望像您这样的代码在子类中生成将 a 设置为 undefined 的 JavaScript,即使您的意图只是缩小基类的类型。布莱克。

所以,在 TypeScript 3.7 中,a --useDefineForClassFields flag was added, along with the declare property modifier。如果您使用--useDefineForClassFields,编译器将输出符合预期的Object.defineProperty() 类字段语义的代码:

如果你run your code as-is with that flag,你会在运行时看到问题:

new Two().doStuff()
// [ERR]: "Executed JavaScript Failed:" 
// [ERR]: this.a is undefined 

解决方案是使用declare 属性修饰符来缩小子类属性,而不发出任何对应的Object.defineProperty() 代码:

class Two extends One {
  declare protected a: B // okay

  constructor() {
    super(new B());
  }

  doStuff() {
    this.a.doSomething()
  }
}

new Two().doStuff(); // okay now

Playground link to code

【讨论】:

    猜你喜欢
    • 2021-06-23
    • 2021-05-09
    • 2021-11-29
    • 2021-04-13
    • 2021-05-21
    • 2021-05-06
    • 1970-01-01
    • 2021-09-04
    • 2021-08-14
    相关资源
    最近更新 更多