プロパティ '…'には初期化子がなく、コンストラクターで明確に割り当てられていません


131

私の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」プロパティで私は間違いを犯しています。どうしたらいいのかわからない...

間違い

回答:


73

TypeScriptの最新バージョンを使用していると思います。の「厳密なクラスの初期化」のセクションを参照してくださいlink

これを修正する方法は2つあります。

A. VSCodeを使用している場合は、エディターが使用するTSバージョンを変更する必要があります。

B.コンストラクター内で配列を宣言するときに、配列を初期化するだけです。

makes: any[] = [];

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

申し訳ありませんが、私はtypescriptを初めて使用します。私の間違いはどこにあると言えますか?
Michael Kostiuchenko 2018

2
エラーが示すように、変数をある値に初期化する必要があります。any[] = [];
Sajeetharan

1
次のようにして、実行時にこの変数が値を持っていることをtypescriptです伝えるために「確実な代入のアサーション」を使用する必要がありますmakes!: any[];
フセインAkar

203

ちょうどに行くtsconfig.jsonとセット

"strictPropertyInitialization": false

コンパイルエラーを取り除くため。

それ以外の場合は、すべての変数を初期化する必要があり、少し面倒です。


3
「strict」の後に必ず追加してください。trueでない場合、トランスパイラーは再びオンになっているように見えます(ただし、VSはオフになっていることを認識しているようです)。
monty 2018年

51
このようにして、すべてのプロジェクトの厳密なチェックプロパティの初期化を無効にします。!変数名に接尾辞演算子を追加するか、このケースを無視するか、コンストラクター内で変数を初期化することをお勧めします。
Matteo Guarnerio 2018

10
あなたはコンパイラが言っている潜在的な問題を無視することを提案しています、これは本当に安全ではありません。だから反対票を投じる。
オルガ

6
StrictPropertyInitialzerは、typescript2.7で導入されたフラグです。これらすべてのフラグを有効にし、すべてのルールに厳密に従うか、一部の検証をオフにするかは、すべての人が選択できます。毎回すべてのルールに従うことはまったく意味がありません。コードが冗長になりすぎて欠点があり、利点よりも大きい場合は、必ずオフにする必要があります。私は...これはすべてのケースでのベストプラクティスが、ほとんどの場合、そのdefinetly実行可能な選択肢であることを語っていないのです
マーティンCuKα線

2
falseに設定しても同じエラーが発生しますが、何が問題なのですか?私はVSのコードを使用しています
sertsedat

64

TypeScript 2.7には、コンストラクターですべてのプロパティを初期化する必要がある厳密なクラスチェックが含まれているためです。回避策は!、変数名に接尾辞としてを追加することです。

makes!: any[];

12
「!」構文は、値がすぐに定義されることを保証できない一般的なケースに存在します。これはエスケープハッチであり、コードの安全性が低下する可能性があるため、信頼しないでください。通常、デフォルト値が推奨されます。しかし、それが存在することを知っておくとよい
kingdaro 2018

@kingdaroは正しいです。これは一般的に使用できますが、フラットが機能しないコードにつながる可能性もあります。例として、VS2017によって生成された基本的なWebアプリで、「!」を追加して、fetchdata.components.tsの予測の割り当てを変更します。(公共予想!:WeatherForecastは[];)と、それは完全にエラーが発生します
IronRod

これは最良の解決策です。@ Input()デコレータの直後(新しい角度で)であるため、特定のコンポーネントを読み取るときに、自然に読み取り、開発ミスを排除します。
ELI7VH

21

Angularプロジェクトを厳密モードでコンパイルするためProperty has no initializer and is not definitely assigned in the constructortsconfig.jsonファイルに構成を追加すると、次のメッセージが表示される場合があります。

"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メソッドは入力バインディングの試行後に呼び出され、バインディングに実際の入力が提供された場合にのみ呼び出されます。


これは、「strict」モードを使用する場合の正解です
RnDrx

8

本当に初期化したくない場合は、次のこともできます。

makes?: any[];

8

--strictPropertyInitializationSajeetharanが参照したを無効にするか、初期化要件を満たすために次のようなことを行う必要があります。

makes: any[] = [];

6

TypeScript 2.7.2以降、宣言の時点でプロパティが割り当てられていない場合は、コンストラクターでプロパティを初期化する必要があります。

Vueから来ている場合は、次のことを試すことができます。

  • "strictPropertyInitialization": truetsconfig.jsonに追加します

  • 無効にすることに不満がある場合は、これを試すこともできますmakes: any[] | undefined。これを行うには、nullチェック(?.)演算子を使用してプロパティにアクセスする必要があります。this.makes?.length

  • 試してみるのもよいでしょうmakes!: any[];。これは、実行時に値が割り当てられることをTSに通知します。

4

typescript@2.9.2を使用してアップグレードする場合、そのコンパイラは、コンポーネントクラスコンストラクタ内の配列型宣言の規則に従います。

この問題を修正するには、コードで宣言されているコードを変更するか、コンパイラを使用せずにプロパティ「strictPropertyInitialization」を追加します「tsconfig.json」ファイルにfalseを追加して、npmstartを再度実行します。

www.jtechweb.inにアクセスできるAngularWebおよびモバイルアプリケーション開発


3

明確な割り当てアサーションを使用することはできませんか?(https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#definite-assignment-assertionsを参照してください

つまり、プロパティをmakes!: any[];!として宣言します。実行時に確実に値があることをtypescriptに保証します。

申し訳ありませんが、これをAngularで試したことはありませんが、Reactでまったく同じ問題が発生したときにうまく機能しました。


公式ドキュメントに記載されているので、すべてのバージョンで作業してみました。ありがとう!
HusseinAkar20年

3

Angularプロジェクトにノードを追加するときにこのエラーが発生します-

TSエラー:?TypeScriptをコンパイルできません:(パス)/base.api.ts:19:13-エラーTS2564:プロパティ 'apiRoot Path'には初期化子がなく、コンストラクターで明確に割り当てられていません。

プライベートapiRootPath:文字列;

解決 -

tsconfig.jsonの"strictPropertyInitialization": false「compilerOptions」に追加されました。

私の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/


2

エラーは正当なものであり、アプリのクラッシュを防ぐ可能性があります。makes配列として入力しましたが、未定義にすることもできます。

2つのオプションがあります(typescriptの既存の理由を無効にする代わりに...):

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[]

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.