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

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


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

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

A.如果你正在使用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和set

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

来消除编译错误。

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


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

makes?: any[];

当您使用typescript@2.9.2进行升级时,它的编译器严格遵守组件类构造函数内部数组类型声明的规则。

为了解决这个问题,要么改变代码中声明的代码,要么避免编译器在“tsconfig. properties”中添加属性“strictPropertyInitialization”:false。然后再次运行NPM start。

Angular web和移动应用开发你可以访问www.jtechweb.in


在tsconfig中添加一些配置时,我们可能会得到这样的消息:Property没有初始化式,并且在构造函数中没有明确地赋值。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 {
}

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

告诉编译器这一点的方法是添加!明确赋值断言运算符,如:

@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)

即声明财产为使!:任何[];!确保typescript在运行时肯定会有一个值。

抱歉,我还没有在angular中尝试过,但当我在React中遇到完全相同的问题时,它对我来说很有用。


从TypeScript 2.7.2开始,如果一个属性在声明时没有赋值,你需要在构造函数中初始化它。

如果你来自Vue,你可以尝试以下方法:

在tsconfig.json中添加"strictPropertyInitialization": true 如果你对禁用它不满意,你也可以尝试这个makes: any[] | undefined。这样做需要使用空检查(?.)操作符访问属性,即this.makes?.length 你也可以尝试一下!: any[];,这告诉TS将在运行时赋值。


该错误是合法的,可以防止应用程序崩溃。你输入了一个数组,但它也可以是未定义的。

你有两个选项(而不是禁用typescript存在的原因…):

1. 在你的情况下,最好是输入make,尽可能未定义。

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

所以当你试图访问make时,编译器会告诉你它可能是未定义的。 否则,如果下面的// <——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[] 

更具体地说,

你的代码设计可以做得更好。定义一个局部可变变量通常不是一个好的实践。你应该在你的服务中管理数据存储:

首先是nullsafe, 其次,能够分解大量代码(包括输入,加载状态和错误) 最后避免多次无用的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'没有初始化式,在构造函数中没有明确赋值。 private apiRootPath:字符串;

解决方案-

在tsconfig.json的compilerOptions中增加了"strictPropertyInitialization": false。

我的包。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年更新:

有一个属性像"strictPropertyInitialization"

只需转到tsconfig。Json和set

“严格”:假的

来消除编译错误。

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

这个错误背后的原因是:

typescript是一种比javascript更安全的语言。 尽管这种安全性是通过启用严格特性来增强的。所以每次当你初始化一个变量时,typescript都希望它们赋一个值。


变量"?"旁边你可以把它。

例子:

---------> id吗?数量: ---------> 的名字吗?:字符串


另一种修复变量必须保持未初始化(在运行时处理)情况的方法是在类型中添加undefined(这实际上是由VC Code建议的)。例子:

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

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


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

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

myText: string ;
}

make变量后加一个问号。

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

  constructor(private makeService: MakeService) { }

现在应该可以工作了。 我使用的是angular 12,它可以在我的代码中工作。


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


一个更好的方法是在变量的末尾加上感叹号,因为你确定它不是undefined或null,例如你正在使用一个ElementRef,需要从模板加载,不能在构造函数中定义,做如下所示的事情

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

这个已经在Angular Github的https://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).

新版本的typescript引入了严格的类初始化,这意味着你需要在构造函数体中初始化类中的所有属性,或者通过属性初始化器。在typescript文档中检查它 为了避免这种情况,您可以添加(!或者?

make!: any[] or make? : any[] 

否则,如果您希望在项目中永久删除严格类检查 你可以在tsconfig中设置strictPropertyInitialization": false。json文件

" compilerOptions ": { .... “noImplicitReturns”:假的, .... “strictPropertyInitialization”:假的 },


在tsconfig.json中添加这两行

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

并确保strict设置为true


直接进入tsconfig。Ts和add "strictPropertyInitialization": false,进入compilerOptions对象。

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

例子:

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

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

"strictPropertyInitialization": false,


如果您不想更改您的tsconfig。Json,你可以这样定义你的类:

class Address{
  street: string = ''
}

或者,你也可以这样做:

class Address{
  street!: string
}

通过在变量名后添加感叹号“!”,Typescript将确保该变量不是null或未定义的。


你也可以添加@ts-ignore来使编译器只在这种情况下静音:

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

属性”……'没有初始化式,在Angular的构造函数错误修复中也没有明确赋值

解决方法1:关闭strictPropertyInitialization标志

在Angular应用中修复这个错误的简单方法是在tsconfig中的typescript编译器选项中禁用——strictPropertyInitialization标志。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();
      }
     
    }

在我的情况下,它与不同的声明根据新的typescript严格的特性:

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

如果在tsonfig中禁用typescript新的严格特性。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/


遵循2个步骤来解决这个问题:

"strictPropertyInitialization": tsconfig.json中的错误条目 ctrl+c在终端上停止你的服务器(检查终端,它在哪里运行),然后用你使用的命令再次运行它,比如ng serve 这2个步骤,应该可以解决你的问题。因为它解决了我的问题。欢呼声……;)


您可以为变量指定一个初始值,而不是关闭严格模式。 例如:

make: any[] = [null]; Private year: number = 0;


这是因为typescript 2.7.2包含了严格的类检查,其中所有属性都应该在构造函数中声明。所以要解决这个问题,只需添加一个感叹号(!),比如:

name!:string;