Typescript “如何修复”;属性没有初始值设定项,并且在构造函数中没有明确指定;错误?

Typescript “如何修复”;属性没有初始值设定项,并且在构造函数中没有明确指定;错误?,typescript,typescript-class,Typescript,Typescript Class,我对这些课程有问题。我想使用方法doSomething()专用于类B,而不是每次都使用类型强制转换,但是当我将属性a指定为类型B时,它告诉我它没有在构造函数中赋值,这有点错误,因为父构造函数进行赋值 A类{ } B类扩展了A类{ doSomething(){} } 一班{ 构造函数(受保护的a:a){} } 第二类扩展一类{ 受保护的a:B//属性“a”没有初始值设定项,并且未在构造函数中明确指定。 构造函数(){ 超级(新B()); //如果我在这里输入“this.a=new B();”,则错

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

A类{
}
B类扩展了A类{
doSomething(){}
}
一班{
构造函数(受保护的a:a){}
}
第二类扩展一类{
受保护的a:B//属性“a”没有初始值设定项,并且未在构造函数中明确指定。
构造函数(){
超级(新B());
//如果我在这里输入“this.a=new B();”,则错误消失,但代码是多余的。
}
多斯塔夫(){
这个
}
}
我做错了什么


问题在于,添加到JavaScript的建议与您可能期望的以及TypeScript设计者在将它们添加到TypeScript时期望的语义不同。事实证明,在JavaScript中,类字段声明将通过而不是通过赋值进行初始化,并且所有没有初始化器的声明字段都将使用
未定义的
进行初始化。因此,最终您可以期望像您这样的代码生成JavaScript,将子类中的
a
设置为
undefined
,即使您的目的只是从基类中缩小类型。布莱奇

因此,在TypeScript 3.7中。如果使用
--useDefineForClassFields
,编译器将输出与类字段的预期
对象一致的代码。defineProperty()
语义:

如果您愿意,您将在运行时看到问题:

new Two().doStuff()
// [ERR]: "Executed JavaScript Failed:" 
// [ERR]: this.a is undefined 
解决方案是使用
declare
property修饰符缩小子类属性的范围,而不发出任何相应的
对象。defineProperty()
code:

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

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

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

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

问题在于,添加到JavaScript的建议与您可能期望的以及TypeScript设计者在将它们添加到TypeScript时期望的语义不同。事实证明,在JavaScript中,类字段声明将通过而不是通过赋值进行初始化,并且所有没有初始化器的声明字段都将使用
未定义的
进行初始化。因此,最终您可以期望像您这样的代码生成JavaScript,将子类中的
a
设置为
undefined
,即使您的目的只是从基类中缩小类型。布莱奇

因此,在TypeScript 3.7中。如果使用
--useDefineForClassFields
,编译器将输出与类字段的预期
对象一致的代码。defineProperty()
语义:

如果您愿意,您将在运行时看到问题:

new Two().doStuff()
// [ERR]: "Executed JavaScript Failed:" 
// [ERR]: this.a is undefined 
解决方案是使用
declare
property修饰符缩小子类属性的范围,而不发出任何相应的
对象。defineProperty()
code:

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

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

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

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

您说父类构造函数执行赋值,但在您提供的代码中父类构造函数中没有赋值。哪一个是真的?注意,请不要添加不相关的标记。在typescript中,构造函数(受保护的a:a){}是构造函数(a:a){this.a=a;}的简写,是的,但是为什么您希望它在严格模式下不会出错(我知道发出的代码是
constructor(a){this.a=a;}
)?除了jcalz的答案之外,您还可以使用for,这似乎是for-one。您说父构造函数进行赋值,但在您提供的代码中父类构造函数中没有赋值。哪一个是真的?注意,请不要添加不相关的标记。在typescript中,构造函数(受保护的a:a){}是构造函数(a:a){this.a=a;}的简写,是的,但是为什么您希望它在严格模式下不会出错(我知道发出的代码是
constructor(a){this.a=a;}
)?除了jcalz的答案之外,你还可以用它,看起来像是一对一。