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

JavascriptAngularTypescript

Javascript Problem Overview


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

Javascript Solutions


Solution 1 - Javascript

Just go to tsconfig.json and set

"strictPropertyInitialization": false

to get rid of the compilation error.

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

Solution 2 - Javascript

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 = [];
}

Solution 3 - Javascript

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

Solution 4 - Javascript

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.

Solution 5 - Javascript

Go to your tsconfig.json file and change the property:

 "noImplicitReturns": false

and then add

 "strictPropertyInitialization": false

under "compilerOptions" property.

Your tsconfig.json file should looks like:


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

>Hope this will help !!

> Good Luck

Solution 6 - Javascript

The error is legitimate and may prevent your app from crashing. You typed makes as an array but it can also be undefined.

You have 2 options (instead of disabling the typescript's reason for existing...):

1. In your case the best is to type makes as possibily undefined.

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

So the compiler will inform you whenever you try to access to makes that it could be undefined. Otherwise, if the // <-- Not ok lines below were executed before getMakes finished or if getMakes failed, your app would crash and a runtime error would be thrown. That's definitely not what you want.

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

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

2. You can assume that it will never fail and that you will never try to access it before initialization by writing the code below (risky!). So the compiler won't take care about it.

makes!: any[] 

More specifically,

Your design could be better. Defining a local and mutable variable is not a good practice. You should manage data storage inside your service:

  • firstly to be nullsafe,
  • secondly to be able to factorise a lot of code (including typing, loading state and errors)
  • finally to avoid mulitple and useless reftech.

The exemple below try to show this but I didn't tested it and it could be improved:

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

Solution 7 - Javascript

Update for 2021 :

> there is property like "strictPropertyInitialization"

Just go to tsconfig.json and set

"strict": false

to get rid of the compilation error.

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

reason behind this error is :

  • typescript is a kind of more Secure lang as compare to javascript.
  • although this security is enhance by enabling strict feature .So every time when you initialize a variable typescript wants them to assign a value.

Solution 8 - Javascript

You either need to disable the --strictPropertyInitialization that Sajeetharan referred to, or do something like this to satisfy the initialization requirement:

makes: any[] = [];

Solution 9 - Javascript

You can also do the following if you really don't want to initialise it.

makes?: any[];

Solution 10 - Javascript

If you want to initialize an object based on an interface you can initialize it empty with following statement.

myObj: IMyObject = {} as IMyObject;

Solution 11 - Javascript

Put a question (?) mark after makes variable.

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

  constructor(private makeService: MakeService) { }

It should now works. I'm using angular 12 and it works on my code.

Solution 12 - Javascript

As of TypeScript 2.7.2, you are required to initialise a property in the constructor if it was not assigned to at the point of declaration.

If you are coming from Vue, you can try the following:

  • Add "strictPropertyInitialization": true to your tsconfig.json

  • If you are unhappy with disabling it you could also try this makes: any[] | undefined. Doing this requires that you access the properties with null check (?.) operator i.e. this.makes?.length

  • You could as well try makes!: any[];, this tells TS that the value will be assigned at runtime.

Solution 13 - Javascript

Get this error at the time of adding Node in my Angular project -

> TSError: ? Unable to compile TypeScript: (path)/base.api.ts:19:13 - error TS2564: Property 'apiRoot Path' has no initializer and is not definitely assigned in the constructor. > > private apiRootPath: string;

Solution -

Added "strictPropertyInitialization": false in 'compilerOptions' of tsconfig.json.

my package.json -

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

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

Solution 14 - Javascript

A batter approach would be to add the exclamation mark to the end of the variable for which you are sure that it shall not be undefined or null, for instance you are using an ElementRef which needs to be loaded from the template and can't be defined in the constructor, do something like below

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

Solution 15 - Javascript

in tsconfig.json file , inside "compilerOptions" add :

"strictPropertyInitialization": false,

enter image description here

Solution 16 - Javascript

if you don't want to change your tsconfig.json, you can define your class like this:

class Address{
  street: string = ''
}

or, you may proceed like this as well:

class Address{
  street!: string
}

by adding an exclamation mark "!" before your variable name, Typescript will be sure that this variable is not null or undefined

Solution 17 - Javascript

there are many solutions

> demo code

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

solutions

  1. add 'undefined' type
class Plant {
  name: string | undefined;
}
  1. add definite assignment assertion
class Plant {
  name!: string;
}
  1. declare with init value 
class Plant {
  name: string = '';
}
  1. use the constructor with an init value 
class Plant {
  name: string;
  constructor() {
    this.name = '';
  }
}
  1. use the constructor and init value by params 
class Plant {
  name: string;
  constructor(name: string) {
    this.name = name ?? '';
  }
}

  1. shorthand of the 5
class Plant {
  constructor(public name: string = name ?? '') {
    // 
  }
}

tsconfig.json

> not recommended

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

refs

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

Solution 18 - Javascript

When you upgrade using [email protected] , its compiler strict the rules follows for array type declare inside the component class constructor.

For fix this issue either change the code where are declared in the code or avoid to compiler to add property "strictPropertyInitialization": false in the "tsconfig.json" file and run again npm start .

Angular web and mobile Application Development you can go to www.jtechweb.in

Solution 19 - Javascript

Another way to fix in the case when the variable must remain uninitialized (and it is dealt with at the run time) is to add undefined to the type (this is actually suggested by VC Code). Example:

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

Depending on actual usage, this might lead to other issues, so I think the best approach is to initialize the properties whenever possible.

Solution 20 - Javascript

Can't you just use a Definite Assignment Assertion? (See https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#definite-assignment-assertions)

i.e. declaring the property as makes!: any[]; The ! assures typescript that there definitely will be a value at runtime.

Sorry I haven't tried this in angular but it worked great for me when I was having the exact same problem in React.

Solution 21 - Javascript

a new version of typescript has introduced strick class Initialization, that is means by all of the properties in your class you need to initialize in the constructor body, or by a property initializer. check it in typescript doccumntation to avoid this you can add (! or ?) with property

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

otherwise, if you wish to remove strick class checking permanently in your project you can set strictPropertyInitialization": false in tsconfig.json file

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

Solution 22 - Javascript

Add these two line on the tsconfig.json

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

and make sure strict is set to true

Solution 23 - Javascript

change the

fieldname?: any[]; 

to this:

fieldname?: any; 

Solution 24 - Javascript

This has been discussed in Angular Github at https://github.com/angular/angular/issues/24571

I think this is what everyone will move to

quote from 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).

Solution 25 - Javascript

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

Solution 1: Disable strictPropertyInitialization flag

The simple way to fix this error in Angular applications is to disable --strictPropertyInitialization flag in typescript compiler options in tsconfig.json file.

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

Solution 2: Adding undefined type to the property

It’s ok to have an undefined property.

So while declaring variable add undefined type to the property.

employees: Employee[];

//Change to 

employees : Employee[] | undefined;

Solution 3: Add definite assignment assertion to property

If you know that we will assign the property in later point in time.

It’s better to add definite assignment assertion to the property. i.e., employees.

employees!: Employee[];

Solution 4: Add initializer to property

Another way to make this type error go away is to add an explicit initializer to the property.

employees: Employee[] = [];

Solution 5: Assignment in the Constructor

Otherwise, we can assign some default value to the property in the constructor.

employees: Employee[];

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

Best Solutions from here

Solution 26 - Javascript

You can declare property in constructor like this:

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

myText: string ;
}

Solution 27 - Javascript

JUST go to the tsconfig.ts and add "strictPropertyInitialization": false, into the compilerOptions Object .

  • if it doesn't solve yet, kindly re-open your Code Editor.

EXAMPLE:

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

Solution 28 - Javascript

Comment the //"strict": true line in tsconfig.json file.

Solution 29 - Javascript

You can also add @ts-ignore to silence the compiler only for this case:

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

Solution 30 - Javascript

Next to variables "?" You can fix it by putting it.

Example:

--------->id?:number --------->name?:string

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMichael KostiuchenkoView Question on Stackoverflow
Solution 1 - JavascriptMartin ČukaView Answer on Stackoverflow
Solution 2 - JavascriptSajeetharanView Answer on Stackoverflow
Solution 3 - JavascriptHarinathView Answer on Stackoverflow
Solution 4 - JavascriptStephaneView Answer on Stackoverflow
Solution 5 - JavascriptcrispengariView Answer on Stackoverflow
Solution 6 - JavascriptAlexandre AnnicView Answer on Stackoverflow
Solution 7 - JavascriptSumitView Answer on Stackoverflow
Solution 8 - JavascriptkshetlineView Answer on Stackoverflow
Solution 9 - JavascriptSpeedOfSpinView Answer on Stackoverflow
Solution 10 - JavascriptUserinoView Answer on Stackoverflow
Solution 11 - JavascriptMd WahidView Answer on Stackoverflow
Solution 12 - JavascriptcodejockieView Answer on Stackoverflow
Solution 13 - JavascriptPinakiView Answer on Stackoverflow
Solution 14 - JavascriptTheMysteriousView Answer on Stackoverflow
Solution 15 - JavascriptM KomaeiView Answer on Stackoverflow
Solution 16 - JavascriptsamivicView Answer on Stackoverflow
Solution 17 - JavascriptxgqfrmsView Answer on Stackoverflow
Solution 18 - JavascriptJai Govind GuptaView Answer on Stackoverflow
Solution 19 - JavascriptAlexei - check CodidactView Answer on Stackoverflow
Solution 20 - JavascriptAndyView Answer on Stackoverflow
Solution 21 - JavascriptTakesha KaluarachchiView Answer on Stackoverflow
Solution 22 - JavascriptSydney_devView Answer on Stackoverflow
Solution 23 - JavascriptMAM.AASIMView Answer on Stackoverflow
Solution 24 - JavascriptmaxisamView Answer on Stackoverflow
Solution 25 - JavascriptMasoud BimmarView Answer on Stackoverflow
Solution 26 - Javascriptkeivan kashaniView Answer on Stackoverflow
Solution 27 - JavascriptTabish ZamanView Answer on Stackoverflow
Solution 28 - JavascriptSureshView Answer on Stackoverflow
Solution 29 - JavascriptHolger RattenscheidView Answer on Stackoverflow
Solution 30 - JavascriptOrkunPinarkayaView Answer on Stackoverflow