Die Eigenschaft '…' hat keinen Initialisierer und wird im Konstruktor nicht definitiv zugewiesen

105

In meiner Angular App habe ich eine Komponente:

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);
  }
}

aber in der Eigenschaft "macht" habe ich einen Fehler. Ich weiß nicht, was ich damit anfangen soll ...

Fehler

Michael Kostiuchenko
quelle

Antworten:

62

Ich denke, Sie verwenden die neueste Version von TypeScript. Weitere Informationen finden Sie im Abschnitt "Strikte Klasseninitialisierung" im link.

Es gibt zwei Möglichkeiten, dies zu beheben:

A. Wenn Sie VSCode verwenden, müssen Sie die vom Editor verwendete TS-Version ändern.

B. Initialisieren Sie das Array einfach, wenn Sie es im Konstruktor deklarieren.

makes: any[] = [];

constructor(private makeService: MakeService) { 
   // Initialization inside the constructor
   this.makes = [];
}
Sajeetharan
quelle
Entschuldigung, ich bin neu im Typoskript. Kannst du sagen, wo mein Fehler ist?
Michael Kostiuchenko
2
Wie der Fehler besagt, müssen Sie die Variable auf einen Wert initialisieren. make: any [] = [];
Sajeetharan
163

Gehen Sie einfach zu tsconfig.json und setzen Sie

"strictPropertyInitialization": false

um den Kompilierungsfehler zu beseitigen.

Andernfalls müssen Sie alle Ihre Variablen initialisieren, was etwas ärgerlich ist

Martin Čuka
quelle
3
Stellen Sie einfach sicher, dass Sie das nach "strict" hinzufügen: true, sonst scheint der Transpiler es wieder einzuschalten (obwohl VS zu wissen scheint, dass es ausgeschaltet ist).
Montag,
35
Auf diese Weise deaktivieren Sie die strikte Überprüfung der Eigenschaftsinitialisierung für das gesamte Projekt. Es ist besser, den !Postfix-Operator zum Variablennamen hinzuzufügen , diesen Fall einfach zu ignorieren oder die Variable im Konstruktor zu initialisieren.
Matteo Guarnerio
6
Sie schlagen vor, potenzielle Probleme, über die der Compiler berichtet, zu ignorieren. Dies ist nicht wirklich sicher. Also abstimmen.
Olga
6
StrictPropertyInitialzer ist ein in Typoskript 2.7 eingeführtes Flag. Es liegt an jedem zu entscheiden, ob Sie alle diese Flags aktivieren und alle Regeln genau befolgen oder eine Validierung deaktivieren möchten. Es macht überhaupt keinen Sinn, jedes Mal alle Regeln zu befolgen. Wenn Ihr Code zu ausführlich und nachteilig wird und größer als die Vorteile ist, sollten Sie ihn auf jeden Fall deaktivieren. Ich sage nicht, dass dies in allen Fällen die beste Vorgehensweise ist, aber in den meisten Fällen die definitiv praktikable Option ...
Martin Čuka
1
Wie ich in meiner Antwort erwähnt habe, haben Sie zwei Möglichkeiten: Entweder deaktivieren Sie die Validierung oder Sie initialisieren alle Variablen. Es liegt an jedem zu entscheiden, was Sie von Projekt zu Projekt mehr profitieren.
Martin Čuka
49

Dies liegt daran, dass TypeScript 2.7 eine strenge Klassenprüfung enthält, bei der alle Eigenschaften im Konstruktor initialisiert werden sollen. Eine Problemumgehung besteht darin, das !als Postfix zum Variablennamen hinzuzufügen :

makes!: any[];
Harinath
quelle
12
Das "!" Die Syntax ist für häufig vorkommende Fälle vorhanden, in denen Sie nicht garantieren können, dass der Wert sofort definiert wird. Es ist eine Notluke und sollte nicht als verlässlich angesehen werden, da dies Ihren Code weniger sicher machen kann. Ein Standardwert wird normalerweise bevorzugt. Gut zu wissen, dass es existiert
Kingdaro
@kingdaro ist richtig. Dies kann zwar im Allgemeinen verwendet werden, kann aber auch dazu führen, dass Code nicht funktioniert. Ändern Sie beispielsweise in der von VS2017 generierten Basis-Webanwendung die Zuordnung für die Prognosen in fetchdata.components.ts, indem Sie das '!' (öffentliche Prognosen!: WeatherForecast [];) und es wird dazu führen, dass es komplett
ausfällt
14

Möglicherweise wird die folgende Meldung angezeigt, Property has no initializer and is not definitely assigned in the constructorwenn der tsconfig.jsonDatei eine Konfiguration hinzugefügt wird , damit ein Angular-Projekt im strengen Modus kompiliert wird:

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

In der Tat beschwert sich der Compiler dann darüber, dass eine Mitgliedsvariable vor ihrer Verwendung nicht definiert wurde.

Für ein Beispiel einer Mitgliedsvariablen, die zur Kompilierungszeit nicht definiert ist, eine Mitgliedsvariable mit einer @InputDirektive:

@Input() userId: string;

Wir könnten den Compiler zum Schweigen bringen, indem wir angeben, dass die Variable optional sein kann:

@Input() userId?: string;

Aber dann müssten wir uns mit dem Fall befassen, dass die Variable nicht definiert wird, und den Quellcode mit einigen solchen Anweisungen überladen:

if (this.userId) {
} else {
}

Wenn wir wissen, dass der Wert dieser Mitgliedsvariablen zeitlich definiert wird, dh vor der Verwendung definiert wird, können wir dem Compiler mitteilen, dass er sich keine Sorgen machen soll, dass er nicht definiert wird.

Die Möglichkeit, dies dem Compiler mitzuteilen, besteht darin, den ! definite assignment assertionOperator wie folgt hinzuzufügen :

@Input() userId!: string;

Jetzt versteht der Compiler, dass diese Variable, obwohl sie zur Kompilierungszeit nicht definiert ist, zur Laufzeit und rechtzeitig definiert werden soll, bevor sie verwendet wird.

Es ist nun Sache der Anwendung, sicherzustellen, dass diese Variable definiert ist, bevor sie verwendet wird.

Als zusätzlichen Schutz können wir behaupten, dass die Variable definiert wird, bevor wir sie verwenden.

Wir können behaupten, dass die Variable definiert ist, dh die erforderliche Eingabebindung wurde tatsächlich vom aufrufenden Kontext bereitgestellt:

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();
}

Da die Variable definiert wurde, kann sie jetzt verwendet werden:

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

Beachten Sie, dass die ngOnInitMethode nach dem Versuch der Eingabebindungen aufgerufen wird, auch wenn für die Bindungen keine tatsächliche Eingabe bereitgestellt wurde.

Während die ngOnChangesMethode nach dem Versuch der Eingabebindungen aufgerufen wird, und nur, wenn tatsächlich eine Eingabe für die Bindungen bereitgestellt wurde.

Stephane
quelle
Dies ist die richtige Antwort, wenn Sie den 'strengen' Modus verwenden
RnDrx
9

Sie müssen entweder --strictPropertyInitializationdas Sajeetharan-Dokument deaktivieren oder etwas Ähnliches tun, um die Initialisierungsanforderungen zu erfüllen:

makes: any[] = [];
kshetline
quelle
6

Sie können auch Folgendes tun, wenn Sie es wirklich nicht initialisieren möchten.

makes?: any[];
SpeedOfSpin
quelle
5

Ab TypeScript 2.7.2 müssen Sie eine Eigenschaft im Konstruktor initialisieren, wenn sie zum Zeitpunkt der Deklaration nicht zugewiesen wurde.

Wenn Sie aus Vue kommen, können Sie Folgendes versuchen:

  • Fügen Sie "strictPropertyInitialization": trueIhrer tsconfig.json hinzu

  • Wenn Sie mit dem Deaktivieren nicht zufrieden sind, können Sie dies auch versuchen makes: any[] | undefined. Dazu müssen Sie mit dem ?.Operator null check ( ) auf die Eigenschaften zugreifenthis.makes?.length

  • Sie können auch versuchen makes!: any[];, dies teilt TS mit, dass der Wert zur Laufzeit zugewiesen wird.
Codejockie
quelle
3

Wenn Sie ein Upgrade mit [email protected] durchführen, befolgt der Compiler strikt die Regeln für die Deklaration des Array-Typs im Komponentenklassenkonstruktor.

Um dieses Problem zu beheben, ändern Sie entweder den Code, der im Code deklariert ist, oder vermeiden Sie es, vom Compiler die Eigenschaft "strictPropertyInitialization": false in die Datei "tsconfig.json" einzufügen , und führen Sie npm start erneut aus.

Angular Web und Mobile Application Development finden Sie unter www.jtechweb.in

Jai Govind Gupta
quelle