Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Property '...' has no initializer and is not definitely assigned in the constructor

in my Angular app i have a component:

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

but in the "makes" property I have a mistake. I dont know what to do with it...

mistake

like image 872
Michael Kostiuchenko Avatar asked Apr 06 '18 18:04

Michael Kostiuchenko


People also ask

What has no initializer and is not definitely assigned in the constructor object?

The error "Property has no initializer and is not definitely assigned in the constructor" occurs when we declare a class property without initializing it. To solve the error, provide an initial value for the class property, e.g. name: string = 'James'; or use a non-null assertion.


4 Answers

Just go to tsconfig.json and set

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

to get rid of the compilation error.

Otherwise you need to initialize all your variables which is a little bit annoying

like image 119
Martin Čuka Avatar answered Oct 22 '22 18:10

Martin Čuka


I think you are using the latest version of TypeScript. Please see the section "Strict Class Initialization" in the link.

There are two ways to fix this:

A. If you are using VSCode you need to change the TS version that the editor use.

B. Just initialize the array when you declare it

makes: any[] = [];

or inside the constructor:

constructor(private makeService: MakeService) { 
   // Initialization inside the constructor
   this.makes = [];
}
like image 23
Sajeetharan Avatar answered Oct 22 '22 18:10

Sajeetharan


It is because TypeScript 2.7 includes a strict class checking where all the properties should be initialized in the constructor. A workaround is to add the ! as a postfix to the variable name:

makes!: any[];
like image 268
Harinath Avatar answered Oct 22 '22 18:10

Harinath


We may get the message Property has no initializer and is not definitely assigned in the constructor when adding some configuration in the tsconfig.json file so as to have an Angular project compiled in strict mode:

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

Indeed the compiler then complains that a member variable is not defined before being used.

For an example of a member variable that is not defined at compile time, a member variable having an @Input directive:

@Input() userId: string;

We could silence the compiler by stating the variable may be optional:

@Input() userId?: string;

But then, we would have to deal with the case of the variable not being defined, and clutter the source code with some such statements:

if (this.userId) {
} else {
}

Instead, knowing the value of this member variable would be defined in time, that is, it would be defined before being used, we can tell the compiler not to worry about it not being defined.

The way to tell this to the compiler is to add the ! definite assignment assertion operator, as in:

@Input() userId!: string;

Now, the compiler understands that this variable, although not defined at compile time, shall be defined at run-time, and in time, before it is being used.

It is now up to the application to ensure this variable is defined before being used.

As an an added protection, we can assert the variable is being defined, before we use it.

We can assert the variable is defined, that is, the required input binding was actually provided by the calling context:

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

Knowing the variable was defined, the variable can now be used:

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

Note that the ngOnInit method is called after the input bindings attempt, this, even if no actual input was provided to the bindings.

Whereas the ngOnChanges method is called after the input bindings attempt, and only if there was actual input provided to the bindings.

like image 146
Stephane Avatar answered Oct 22 '22 18:10

Stephane