属性'…'没有初始化器,也没有在构造函数中明确赋值

在我的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);
}
}

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

错误

884742 次浏览

我认为您使用的是最新版本的TypeScript。请参阅link中的“严格类初始化”部分。

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

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

B.声明数组时初始化数组

makes: any[] = [];

或者在构造函数中:

constructor(private makeService: MakeService) {
// Initialization inside the constructor
this.makes = [];
}

您需要禁用--strictPropertyInitialization Sajeetharan引用,或做类似的事情来满足初始化要求:

makes: any[] = [];

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

makes!: any[];

只需转到tsconfig.json并设置

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

摆脱编译错误。

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

如果您真的不想初始化它,您也可以执行以下操作。

makes?: any[];

使用typescript@2.9.2升级时,其编译器严格遵循组件类构造函数内数组类型声明的规则。

要修复此问题,请更改代码中声明的代码或避免编译器在“tsconfig.json”文件中添加属性//严格的属性初始化,为false并再次运行npm start。

Angular Web和移动应用程序开发你可以去www.jtechweb.in

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

"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方法是在输入绑定尝试之后调用的,并且仅当有实际输入提供给绑定时。

你不能只使用明确的赋值断言吗?(见https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#definite-assignment-assertions

即将属性声明为makes!: any[]; The!确保打字脚本在运行时肯定会有一个值。

对不起,我没有尝试过这个角度,但当我在React中遇到完全相同的问题时,它对我来说非常有效。

从TypeScript 2.7.2开始,如果在声明时未将属性分配给,则需要在构造函数中初始化属性。

如果您来自Vue,您可以尝试以下操作:

  • "strictPropertyInitialization": true添加到您的tsconfig.json

  • 如果您对禁用它不满意,您也可以尝试此makes: any[] | undefined。这样做需要使用空检查(?.)运算符访问属性,即this.makes?.length

  • 您也可以尝试makes!: any[];,这告诉TS该值将在运行时分配。

错误为合法,可能会阻止您的应用程序崩溃。您键入了makes作为数组,但它也可以是未定义的。

您有2个选项(而不是禁用打字稿的现有原因…):

1.在您的情况下,最好键入makes作为可能未定义。

makes?: any[]
// or
makes: any[] | undefined

因此,每当您尝试访问makes时,编译器都会通知您它可能未定义。 否则,如果下面的// <-- Not ok行在getMakes完成之前执行,或者如果getMakes失败,您的应用程序将崩溃并抛出运行时错误。这绝对不是您想要的。

makes[0] // <-- Not ok
makes.map(...) // <-- Not ok


if (makes) makes[0] // <-- Ok
makes?.[0] // <-- Ok
(makes ?? []).map(...) // <-- Ok

2.你可以假设它永远不会失败,并且你永远不会通过编写下面的代码在初始化之前尝试访问它(危险!)。所以编译器不会关心它。

makes!: any[]

更具体地说,

你的代码设计可以更好。定义本地和可变变量通常不是一个好的做法。你应该管理服务内的数据存储:

  • 首先是零安全,
  • 其次,能够分解大量代码(包括键入、加载状态和错误)
  • 最后要避免多次无用的reftech。

下面的示例试图展示这一点,但我没有测试它,它可以改进:

type Make = any // Type it


class MakeService {


private readonly source = new BehaviorSubject<Make[] | undefined>(undefined);
loading = false;


private readonly getMakes = (): Observable<Make[]> => {
/* ... your current implementation */
};


readonly getMakes2 = () => {
if (this.source.value) {
return this.source.asObservable();
}
return new Observable(_ => _.next()).pipe(
tap(_ => {
this.loading = true;
}),
mergeMap(this.getMakes),
mergeMap(data => {
this.source.next(data);
return data;
}),
tap(_ => {
this.loading = false;
}),
catchError((err: any) => {
this.loading = false;
return throwError(err);
}),
);
};
}


@Component({
selector: 'app-vehicle-form',
template: `
<div *ngIf="makeService.loading">Loading...</div>
<div *ngFor="let vehicule of vehicules | async">
\{\{vehicle.name}}
</div>
`,
styleUrls: ['./vehicle-form.component.css']
})
export class VehicleFormComponent implements OnInit {
constructor(public makeService: MakeService) {}


readonly makes = this.makeService.getMakes2().pipe(
tap(makes => console.log('MAKES', makes))
);


readonly vehicules = this.makes.pipe(
map(make => make/* some transformation */),
tap(vehicule => console.log('VEHICLE', vehicule)),
);


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

改变了

fieldname?: any[];

对此:

fieldname?: any;

在我的Angular项目中添加Node时出现此错误-

TSError:?无法编译TypeScript: /base.api.ts:19: 13-错误TS2564:属性apiRoot Path没有初始化器,也没有在构造函数中明确赋值。

请求参数apiRootPath: string;返回值

解决方案-

tsconfig.json的“编译选项”中添加了"strictPropertyInitialization": false

我的package.json-

"dependencies": {
...
"@angular/common": "~10.1.3",
"@types/express": "^4.17.9",
"express": "^4.17.1",
...
}

参考URL-https://www.ryadel.com/en/ts2564-ts-property-has-no-initializer-typescript-error-fix-visual-studio-2017-vs2017/

如果您想初始化基于接口的对象,您可以使用以下语句将其初始化为空。

myObj: IMyObject = {} as IMyObject;

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

 "noImplicitReturns": false

然后添加

 "strictPropertyInitialization": false

"compilerOptions"属性下。

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


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

希望对你有帮助!!!

祝你好运

2021年更新

有像“严格属性初始化”这样的属性

去tsconfig.json

"严格": false

摆脱编译错误。

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

这个错误背后的原因是:

  • 与JavaScript相比,TypeScript是一种更安全的语言。
  • 尽管通过启用严格的功能增强了这种安全性。所以每次初始化变量时,打字脚本都希望它们分配一个值。

在变量旁边“?”你可以通过放它来修复它。

示例:

<>--------->; id?: Number --------->; name?: string

另一种解决变量必须保持未初始化(并且在运行时处理)的方法是将undefined添加到类型中(这实际上是VC代码建议的)。例子:

@Input() availableData: HierarchyItem[] | undefined;
@Input() checkableSettings: CheckableSettings | undefined;

根据实际使用情况,这可能会导致其他问题,所以我认为最好的方法是尽可能初始化属性。

你可以像这样在构造函数中声明属性:

export class Test {
constructor(myText:string) {
this.myText= myText;
}


myText: string ;
}

使变量后放置一个问题(?)标记。

  makes?: any[];
vehicle = {};


constructor(private makeService: MakeService) { }

现在应该可以了。 我正在使用角度12,它适用于我的代码。

注释tsconfig.json文件中的//"strict": true行。

一种更有效的方法是将感叹号添加到变量的末尾,您可以确保它不会被未定义或null,例如您使用的是需要从模板加载并且无法在构造函数中定义的ElementRef,请执行以下操作

class Component {
ViewChild('idname') variable! : ElementRef;
}

这已经在Angular Githubhttps://github.com/angular/angular/issues/24571中讨论过

我想这是每个人都会去的地方

引用自https://github.com/angular/angular/issues/24571#issuecomment-404606595

For angular components, use the following rules in deciding between:
a) adding initializer
b) make the field optional
c) leave the '!'


If the field is annotated with @input - Make the field optional b) or add an initializer a).
If the input is required for the component user - add an assertion in ngOnInit and apply c.
If the field is annotated @ViewChild, @ContentChild - Make the field optional b).
If the field is annotated with @ViewChildren or @ContentChildren - Add back '!' - c).
Fields that have an initializer, but it lives in ngOnInit. - Move the initializer to the constructor.
Fields that have an initializer, but it lives in ngOnInit and cannot be moved because it depends on other @input fields - Add back '!' - c).

一个新版本的类型化引入了strick类初始化,这意味着你需要在构造函数体中初始化类中的所有属性,或者通过属性初始化器。

"编译选项":{ …… //无含义返回值:"noInfoReader": false, …… //严格的属性初始化,为false },

在tsconfig.json上添加这两条线

"noImplicitReturns": true,
"strictPropertyInitialization": false,

并确保严格设置为true

转到tsconfig.ts并添加 “严格属性初始化”:假,自定义编译选项对象中。

  • 如果它还没有解决,请重新打开您的代码编辑器。

示例:

"compilerOptions" : {
"strictPropertyInitialization": false,
}

tsconfig.json文件中,在“compilerOptions”中添加:

"strictPropertyInitialization": false,

在此处输入图片描述

如果你不想改变你的tsconfig.json,你可以像这样定义你的类:

class Address{
street: string = ''
}

或者,你也可以这样做:

class Address{
street!: string
}

通过在变量名后添加感叹号“!”,TypeScript将确保此变量不为空或未定义。

有很多解决方案

演示代码

class Plant {
name: string;
// ❌ Property 'name' has no initializer and is not definitely assigned in the constructor.ts(2564)
}

解决方案

  1. 添加“未定义”类型
class Plant {
name: string | undefined;
}
  1. 添加确定赋值断言
class Plant {
name!: string;
}
  1. 声明初始化值👍
class Plant {
name: string = '';
}
  1. 使用初始化值的构造函数👍
class Plant {
name: string;
constructor() {
this.name = '';
}
}
  1. 通过参数使用构造函数和初始化值👍
class Plant {
name: string;
constructor(name: string) {
this.name = name ?? '';
}
}


  1. 5👍的简写
class Plant {
constructor(public name: string = name ?? '') {
//
}
}


tsconfig.json

不建议

{
"compilerOptions": {
+   "strictPropertyInitialization": false,
-   "strictPropertyInitialization": true,
}
}


裁判

https://www.typescriptlang.org/docs/handbook/2/classes.html#--strictpropertyinitialization

您还可以添加@ts-忽略以仅在这种情况下使编译器沉默:

//@ts-ignore
makes: any[];

属性'…'没有初始化器,并且在Angular的构造函数错误修复中没有明确分配

解决方案1:禁用严格属性初始化标志

在Angular应用程序中修复此错误的简单方法是在文件中的打字脚本编译器选项中禁用tsconfig.json。

"compilerOptions": {
///
,
"strictPropertyInitialization":false
}

解决方案2:向属性添加未定义的类型

可以有一个未定义的属性。

因此,在声明变量时,向属性添加未定义的类型。

employees: Employee[];


//Change to


employees : Employee[] | undefined;

解决方案3:为属性添加明确的赋值断言

如果您知道我们将在稍后的时间点分配房产。

最好在属性中添加明确的分配断言。即员工。

employees!: Employee[];

解决方案4:向属性添加初始化器

消除此类型错误的另一种方法是向属性添加显式初始化程序。

employees: Employee[] = [];

解决方案5:构造函数中的赋值

否则,我们可以为构造函数中的属性分配一些默认值。

employees: Employee[];


constructor() {
this.employees=[];
}

最佳解决方案

1)你可以像下面的代码一样应用它。当你这样做时,系统不会给出错误。

“定义赋值断言”(!)告诉TypeScript我们知道这个值

详细信息

@Injectable()
export class Contact {
public name !:string;
public address!: Address;
public digital!: Digital[];
public phone!: Phone[];
}

2)第二种方法是创建一个构造函数并在此处定义值。

export class Contact {
public name :string;
public address: Address;
public digital: Digital[];
public phone: Phone[];


constructor( _name :string,
_address: Address,
_digital: Digital[],
_phone: Phone[])
{
this.name=_name;
this.address=_address;
this.digital=_digital;
this.phone=_phone;
}
}

3)第三种选择是创建一个get属性并赋值如下

  export class Contact {
public name :string="";
public address: Address=this._address;
    

get _address(): Address {
return new Address();
}
     

}

在我的情况下,它可以根据新的打字稿严格功能使用不同的声明:

@ViewChild(MatSort, {static: true}) sort!: MatSort;

如果禁用打字稿新的严格功能tsonfig.json

"compilerOptions": {
///
,
"strictPropertyInitialization":false
}

旧的Angular指南代码运行良好

@ViewChild(MatSort) sort: MatSort;

这里有4种方法来解决这个问题,这要归功于 Arunkumar Gudelli(2022)https://www.angularjswiki.com/angular/property-has-no-initializer-and-is-not-definitely-assigned-in-the-constructor/

按照两个步骤来解决这个::

  1. “严格属性初始化”:tsconfig.json中的错误条目
  2. ctrl+c在终端上停止您的服务器(检查终端,它正在运行的位置)并使用您使用的命令再次运行它,例如ng service 这两个步骤,应该解决你的问题…因为它解决了我的…干杯…;)