属性 '...' 没有初始值设定项,并且在构造函数中没有明确分配

IT技术 javascript angular typescript
2021-01-16 03:19:52

在我的 Angular 应用程序中,我有一个组件:

import { MakeService } from './../../services/make.service';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-vehicle-form',
  templateUrl: './vehicle-form.component.html',
  styleUrls: ['./vehicle-form.component.css']
})
export class VehicleFormComponent implements OnInit {
  makes: any[];
  vehicle = {};

  constructor(private makeService: MakeService) { }

  ngOnInit() {
    this.makeService.getMakes().subscribe(makes => { this.makes = makes
      console.log("MAKES", this.makes);
    });
  }

  onMakeChange(){
    console.log("VEHICLE", this.vehicle);
  }
}

但是在“makes”属性中我有一个错误。我不知道该怎么办...

错误

6个回答

只需转到tsconfig.json并设置

"strictPropertyInitialization": false

摆脱编译错误。

否则你需要初始化所有的变量,这有点烦人

正如我在回答中提到的,您有两种选择,要么禁用验证,要么初始化所有变量。每个人都可以选择哪个项目能让您从项目中受益更多。
2021-03-23 03:19:52
只要确保在 "strict": true 之后添加它,否则转译器似乎再次打开它(尽管 VS 似乎知道它已关闭)。
2021-04-01 03:19:52
您建议忽略编译器正在讲述的潜在问题,这并不安全。所以投反对票。
2021-04-02 03:19:52
通过这种方式,您将禁用所有项目的严格检查属性初始化。最好!在变量名中添加后缀运算符,忽略这种情况,或者在构造函数中初始化变量。
2021-04-04 03:19:52
StrictPropertyInitialzer 是 typescript 2.7 中引入的标志。每个人都可以选择是否要启用所有这些标志并严格遵守所有规则或关闭某些验证。每次都遵守所有规则是完全没有意义的。如果您的代码变得过于冗长和缺点,并且大于优点,您应该明确地将其关闭。我并不是说这在所有情况下都是最佳实践,但在大多数情况下它绝对是可行的选择......
2021-04-05 03:19:52

我认为您使用的是最新版本的 TypeScript。请参阅link.

有两种方法可以解决这个问题:

A. 如果您使用的是 VSCode,则需要更改编辑器使用的 TS 版本。

B. 只需在构造函数中声明数组时对其进行初始化,

makes: any[] = [];

constructor(private makeService: MakeService) { 
   // Initialization inside the constructor
   this.makes = [];
}
嗨@Sajeetharan,如何更改 vscode ts 版本
2021-03-14 03:19:52
抱歉,我是typescript新手。你能说我的错误在哪里吗?
2021-03-20 03:19:52
在构造函数中初始化变量是一种 Angular 反模式。不要这样做。
2021-03-27 03:19:52
正如错误所说,您需要将变量初始化为某个值: any[] = [];
2021-03-29 03:19:52
您必须使用“Definite Assignment Assertion”来告诉typescript此变量在运行时将具有如下值: makes!: any[];
2021-03-29 03:19:52

这是因为 TypeScript 2.7 包含严格的类检查,所有属性都应在构造函数中初始化。一种解决方法是将!作为后缀添加到变量名称中:

makes!: any[];
这 ”!” 对于那些不能保证立即定义值的常见情况,存在语法。这是一个逃生舱口,不应该被依赖,因为它会使您的代码不那么安全。默认值通常是首选。很高兴知道它存在,虽然
2021-03-22 03:19:52
@kingdaro 是对的。虽然这通常可以使用,但它也可能导致代码无法正常工作。例如,在 VS2017 生成的基本 web 应用程序中,通过添加“!”更改 fetchdata.components.ts 中预测的分配 (公共预测!:WeatherForecast[];)并且它会导致它完全出错
2021-03-22 03:19:52
我需要在应用程序的服务中定义一个使用枚举的属性,我无法假设用户的选择,甚至不是默认值。它在第一步中定义,直到第二步才被读取,所以这是非常有用的转义,很高兴知道它存在,非常感谢。
2021-03-26 03:19:52
顺便说一句,与使用有什么区别!或者 ?处理空值或未定义?
2021-03-29 03:19:52
这是最好的解决方案,因为它直接在 @Input() 装饰器之后(在新的角度中),当读取任何给定的组件时,它会自然地读取并剔除任何开发错误。
2021-04-05 03:19:52

Property has no initializer and is not definitely assigned in the constructortsconfig.json文件中添加一些配置以便在严格模式下编译 Angular 项目时,我们可能会收到消息

"compilerOptions": {
  "strict": true,
  "noImplicitAny": true,
  "noImplicitThis": true,
  "alwaysStrict": true,
  "strictNullChecks": true,
  "strictFunctionTypes": true,
  "strictPropertyInitialization": true,

事实上,编译器然后抱怨成员变量在使用之前没有定义。

对于编译时未定义的成员变量的示例,具有@Input指令的成员变量

@Input() userId: string;

我们可以通过声明变量可能是可选的来使编译器静音:

@Input() userId?: string;

但是,我们将不得不处理未定义变量的情况,并用一些这样的语句来弄乱源代码:

if (this.userId) {
} else {
}

相反,知道这个成员变量的值会被及时定义,也就是在使用之前已经定义,我们可以告诉编译器不要担心它没有被定义。

告诉编译器的方法是添加! definite assignment assertion运算符,如下所示:

@Input() userId!: string;

现在,编译器明白这个变量虽然没有在编译时定义,但应该在运行时定义,并且在使用之前及时定义。

现在由应用程序来确保在使用之前定义此变量。

作为额外的保护,我们可以在使用变量之前断言它正在被定义。

我们可以断言变量已定义,即所需的输入绑定实际上是由调用上下文提供的:

private assertInputsProvided(): void {
  if (!this.userId) {
    throw (new Error("The required input [userId] was not provided"));
  }
}

public ngOnInit(): void {
  // Ensure the input bindings are actually provided at run-time
  this.assertInputsProvided();
}

知道变量已定义,现在可以使用变量:

ngOnChanges() {
  this.userService.get(this.userId)
    .subscribe(user => {
      this.update(user.confirmedEmail);
    });
}

请注意,该ngOnInit方法是在输入绑定尝试之后调用的,即使没有向绑定提供实际输入也是如此。

而在ngOnChanges输入绑定尝试之后调用方法,并且仅当有实际输入提供给绑定时才调用。

除了一件事之外,很多这对我来说都很有意义......断言会给你什么?可以用于调试,但不适用于使用该应用程序。抛出不会被捕获的错误不是一个好主意。您应该提供一些回退,无论如何都可以使事情正常进行。
2021-03-27 03:19:52
这应该被视为正确答案,因为它解决了问题,而不仅仅是转动部分棉绒。
2021-04-03 03:19:52
这是使用“严格”模式时的正确答案
2021-04-09 03:19:52
在严格模式下使用“明确赋值断言”只是为了避免条件检查没有多大意义。您正在破坏拥有严格类型系统的整个逻辑。如果避免这些检查对您来说更重要,那么您可能不应该使用严格模式。
2021-04-09 03:19:52

转到您的tsconfig.json文件并更改属性:

 "noImplicitReturns": false

然后添加

 "strictPropertyInitialization": false

根据"compilerOptions"财产。

您的tsconfig.json文件应如下所示:


{
      ...
      "compilerOptions": {
            ....
            "noImplicitReturns": false,
            ....
            "strictPropertyInitialization": false
      },
      "angularCompilerOptions": {
         ......
      }  
 }

希望这会有所帮助!!

祝你好运

IMO,它有点倒退。
2021-03-15 03:19:52