866

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

H3AR7B3A7
  • 4,366
  • 2
  • 14
  • 37
Mikhail Kostiuchenko
  • 9,121
  • 4
  • 15
  • 28
  • I am wondering: On newer versions of TypeScript, did anyone figured it out how to specify the object type that will reside inside the array? Instead of using Any[]... ✍ – Raul Chiarella Aug 18 '23 at 17:41

37 Answers37

1442

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

Otziii
  • 2,304
  • 1
  • 25
  • 34
Martin Čuka
  • 16,134
  • 4
  • 23
  • 49
  • 39
    Just make sure you add that after "strict": true else the transpiler seems to turn it on again (although VS seems to know it's off). – monty May 18 '18 at 00:01
  • 288
    In this way you will disable the strict checking property initialization for all the project. It's better to add the `!` postfix operator to the variable name, to just ignore this case, or initialize the variable inside the constructor. – Matteo Guarnerio Jul 23 '18 at 08:54
  • 40
    You are suggesting to ignore potential problems that the compiler is telling about, this is not really safe. So downvote. – Olga Oct 12 '18 at 18:52
  • 48
    StrictPropertyInitialzer is a flag introduced in typescript 2.7. It's up to everybody to choose if you want to enable all these flags and strictly follow all rules or turn off some validation. It makes completely no sense to follow all the rules every time. If your code gets too verbose and downsides and are bigger than advantages you should definetly turn it off. I am not telling that this is the best practice in all cases but its definetly viable option in most cases... – Martin Čuka Oct 14 '18 at 21:52
  • 14
    As I mentioned in my answer you have two options either you disable validation OR initialize all variables. Its up to everybody to choose what will you benefit more from project to project. – Martin Čuka Oct 14 '18 at 21:54
  • 2
    when I set it to false it still gives me the same error, what might be the issue? I'm using VS Code – sertsedat Sep 24 '19 at 08:48
  • I thought the whole point of TypeScript was to avoid doing this kind of thing. Wouldn't you at least want to assign `undefined` or `null` or something? – Rei Miyasaka Jan 27 '21 at 22:08
  • 1
    After adding, I needed to restart vsCode to solve it. – ali hasani Feb 03 '21 at 09:43
  • 2
    Thanks! In `tsconfig.json` .. `compilerOptions` ... I updated the value of strict from true to false ... `"strict": false` and it fixed the issue. – spiderman Mar 11 '21 at 07:40
  • 2
    For anyone else wondering, this entry has to be added in the "compilerOptions" parts of tsconfig.json – anaotha Mar 11 '21 at 10:27
  • avoid at all costs removing/disabling compiler or lint options if you are deploying for production – angellica.araujo May 02 '22 at 19:23
  • wow ts won't let you work around this garbage with this.field = null in the constructor either. thanks ts for forcing me to choose bogus initial values for everything, so helpful – Britton Kerin Aug 31 '22 at 21:48
  • This advice is technically an option, but typically inadvisable, because it reduces the effectiveness of TypeScript and overall code quality could go down as a result. In my opinion, this approach is akin to using a sledge hammer to put a screw in a wall... yeah, the screw will go in, but you're also going to damage the wall in the process, and the screw probably isn't going to secure anything effectively anyway. – Dale Harris Oct 07 '22 at 00:47
  • Most of the time it's better to use hammer that you are used to and put screw gently in to the wall so you don't do any damage than have twenty different tools not knowing to use properly even one of them and in the process damage the wall, the screw and yourself. – Martin Čuka Oct 14 '22 at 06:13
  • I think this is a design error of typeorm. Even if you disable it with a `!` you can assign a null that value. It is not required in the constructor anymore... The fact that they do not mention it in their documentation tells already the story. – Arwed Mett Dec 14 '22 at 18:04
  • 1
    As suggested by Matteo Guarnerio, it is best to add ! to assert that this particular variable will be initialized for sure rather than using compiler options to disable the check for the entire application – psaradhi Apr 27 '23 at 15:46
365

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 = [];
}
Clashsoft
  • 11,553
  • 5
  • 40
  • 79
Sajeetharan
  • 216,225
  • 63
  • 350
  • 396
  • 3
    as the error says you need to initialize the variable to some value makes: any[] = []; – Sajeetharan Apr 06 '18 at 18:44
  • 231
    You must use 'Definite Assignment Assertion' to tell typescript that this variable will have a value at runtime as follows: `makes!: any[];` – Hussein Akar Dec 06 '20 at 18:10
  • HI @Sajeetharan, how to chnage vscode ts version – Kumaresan Sd Mar 16 '21 at 12:59
  • 9
    Initializing variables in the constructor is an Angular anti-pattern. Don't do it. – Will Alexander Apr 09 '21 at 16:23
  • 1
    @KumaresanSd `ctrl+shift+p` and type `typescript` in the dropdown, then select "Select TypeScript Version" – Paolo Aug 04 '21 at 22:35
  • @WillAlexander So why Angular Docs say _"the recommended solution is to use a constructor or ngOnInit to set initial values"_ ([src](https://angular.io/errors/NG0100#debugging-the-error)) or _"Constructors should do no more than set the initial local variables to simple values."_ ([src](https://angular.io/guide/lifecycle-hooks#initializing-a-component-or-directive))? – Martin Schneider Mar 17 '23 at 18:45
  • 1
    @MartinSchneider your first source, in context, makes sense. It’s saying “you’re using the wrong lifecycle hook”. Your second source says “no more than”, meaning they can also do less. In practice, putting any logic in constructors has a tendency to make code less clean, as one expects all initializations to be done in ngOnInit. Perhaps it would be more correct of me to call it code smell, rather than an anti-pattern. Still, it’s not good practice. – Will Alexander Mar 20 '23 at 07:03
  • @HusseinAkar Hello! What do you mean? I am using ngOnInit to populate this array of objects of the `interface` type. So I need to include the `!` after the variable declaration, because of that? – Raul Chiarella Aug 18 '23 at 16:28
  • Where did this MakeService come from? – Raul Chiarella Aug 18 '23 at 17:21
  • I tried this multiple times and using multiple ways and can not get it to work. – Raul Chiarella Aug 18 '23 at 19:28
328

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[];
anothernode
  • 5,100
  • 13
  • 43
  • 62
Harinath
  • 3,791
  • 2
  • 16
  • 34
  • 45
    The "!" syntax exists for those common-ish cases where you can't guarantee that the value will be defined immediately. It's an escape hatch, and shouldn't be relied on, as it can make your code less safe. A default value is usually preferred. Good to know it exists, though – kingdaro Apr 28 '18 at 07:42
  • 1
    @kingdaro is right. While this can generally be used, it can also lead to code that flat doesn't work. As an example, in the basic webapp generated by VS2017, change the assignment for the forecasts in fetchdata.components.ts by adding the '!' (public forecasts!: WeatherForecast[];) and it will cause it to completely error out – AdvApp Jun 28 '18 at 15:38
  • 4
    This is the best solution, since it is directly after the @Input() decorator (in the new angular), when reading any given component, it reads naturally and culls out any dev mistakes. – ELI7VH Dec 09 '20 at 18:33
  • 1
    incidentally what is the difference from using ! or ? to handle nulls or undefined? – Darren Street Mar 02 '21 at 13:52
  • I needed to define a property that uses an Enum in a service on an app where I can't assume the user's choices, not even a default. It is defined in the first step and not read until the second, so this was very useful escape, good to know it exists, thanks very much. – ConorJohn Mar 04 '21 at 15:08
  • This is not recommended when the property is assigned within a subscribe or async callback. There will be a short period of time where it is undefined and the template will throw errors. Use ?: – Clashsoft Dec 18 '21 at 11:40
164

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.

Stephane
  • 11,836
  • 25
  • 112
  • 175
  • 12
    this is the correct answer when using 'strict' mode – RnDrx Jun 01 '20 at 17:42
  • 1
    A lot of this makes sense to me apart from one thing... What would the assert give you? Would be fine for debugging, but not for using the app. Throwing errors that will not be caught is not a good idea. You should provide some fallback that will make things work no matter what. – Nux Jan 11 '21 at 01:59
  • 8
    This should be upvoted as the correct answer, as it solves the problem, rather than just turning of part of the linting. – Jesper Pannerup May 19 '21 at 13:05
  • Using "definite assignment assertion" in strict mode just to avoid the condition checks doesn't make great sense. You are undermining the whole logic of having a strict typed system. If avoiding those checks is more important to you, then you probably shouldn't use strict mode. – user3658510 Jun 07 '21 at 00:26
127

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

crispengari
  • 7,901
  • 7
  • 45
  • 53
73

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 code's design could be improved. It is generally not considered best practice to define local and mutable variables. Instead, you should manage data storage within a service:

  • Firstly to ensure null/undefined safety,
  • Secondly to be able to factorise a lot of code (including typing, loading state and errors),
  • Finally to avoid multiple and useless reftech across components.

Here is an example illustrating the concept I am suggesting. Please note that I have not tested it, and there is room for further improvement.

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);
    });
  }
}
Alexandre Annic
  • 9,942
  • 5
  • 36
  • 50
  • 8
    This seems like the only correct solution. I'm horrified by the other answers. – Rei Miyasaka Jan 27 '21 at 22:19
  • 1
    I also consider that this error message is useful. So deactivate it in tsconfig.json is not the appropriate solution. And adding '!' can allows the compiler to let go, but it makes the code less sure, unless you're really sure of what is going on. A better solution seems to understand that the property can be undedinfed, and therefore the developer has to write code accordingly. This is the purpose of the answer to me. – Johan Chouquet Mar 07 '21 at 14:04
  • @Rei Miyasaka, this "feature" was added later to typescript does that mean that all code that was written before is wrong ? No it does not. When you have your hello world application feel free to follow all the rules. But once you have huge project (which is a reason for language like typescript to start with) then you should decide how to write the code and all should follow it. I don't see ANYTHING wrong with disabling this particular option in tsconfig.json. – Martin Čuka Feb 17 '22 at 08:48
  • @MartinČuka Just because everyone was doing it doesn't mean it wasn't wrong or that it wasn't horrifying. TypeScript itself was brought about because JavaScript is kind of horrifying. And the larger the project, the more you should want to be strict with type rules. – Rei Miyasaka Feb 17 '22 at 22:53
  • option 2 adding a `!` before `:` is more common. – seedme Mar 19 '22 at 02:00
37

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

xgqfrms
  • 10,077
  • 1
  • 69
  • 68
28

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.
Sumit
  • 529
  • 5
  • 13
  • 6
    Horrible advice, throws out type safety so that you see fewer errors, rather than surrendering some convenience for safety. – Heretic Monkey Mar 07 '22 at 14:49
  • Apparently, strict option is a combination of several strict type-checking options in TypeScript, including noImplicitAny, strictNullChecks, strictFunctionTypes, strictPropertyInitialization, noImplicitThis, and alwaysStrict. Maybe a bad idea to disable all of that? – Brian Webster Mar 28 '23 at 03:27
23

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

makes: any[] = [];
kshetline
  • 12,547
  • 4
  • 37
  • 73
20
  1. Go to tsconfig.json

  2. add "strictPropertyInitialization": false, in "compilerOptions":

enter image description here

17

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

makes?: any[];
Bronzdragon
  • 345
  • 3
  • 13
SpeedOfSpin
  • 1,611
  • 20
  • 21
15

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

myObj: IMyObject = {} as IMyObject;
Astrophage
  • 1,231
  • 1
  • 12
  • 38
14

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.

Md Wahid
  • 450
  • 5
  • 12
14

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 "!" after your variable name, Typescript will be sure that this variable is not null or undefined.

samivic
  • 1,216
  • 14
  • 13
12

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.
codejockie
  • 9,020
  • 4
  • 40
  • 46
12

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;
}
TheMysterious
  • 219
  • 3
  • 8
10

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

"strictPropertyInitialization": false,

enter image description here

M Komaei
  • 7,006
  • 2
  • 28
  • 34
9

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/

Pinaki
  • 792
  • 8
  • 17
8

When you upgrade using typescript@2.9.2 , 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

8

It is because typescript 2.7.2 included a strict class checking where all properties should be declared in constructor. So to work around that, just add an exclamation mark (!) like:

name!:string;
Alvin Kimata
  • 141
  • 1
  • 6
6

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.

Andy
  • 10,412
  • 13
  • 70
  • 95
6

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.

Alexei - check Codidact
  • 22,016
  • 16
  • 145
  • 164
  • Worked for me when initializing the @ViewChild variable.. see for reference: https://stackblitz.com/edit/ngx-flow-example?file=src%2Fapp%2Fapp.component.html – Kieran Ryan Aug 07 '21 at 12:50
  • 1
    Writing `@Input() availableData: HierarchyItem[] | undefined;` is the same as writing `@Input() availableData?: HierarchyItem[]` ;) – Raphaël Balet Aug 30 '21 at 07:23
6

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 },

  • 2
    What is the difference between '!' and '?' ? – pouyada Jan 15 '22 at 18:30
  • 2
    @pouyada the `!` is assertive assignment declaration saying that no matter what it is assigned even if typescript can't pick it up. `?` is optional meaning it may or may not be there but your component should be prepared for either case. – Mark Hill Feb 03 '22 at 18:29
6

1) You can apply it like the code below. When you do this, the system will not give an error.

"Definite Assignment Assertion" (!) to tell TypeScript that we know this value

Detail info

@Injectable()
export class Contact {
  public name !:string;
  public address!: Address;
  public digital!: Digital[];
  public phone!: Phone[];
}

2) The second method is to create a constructor and define values here.

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) The third choice will be to create a get property and assign a value as follows

  export class Contact {
      public name :string="";
      public address: Address=this._address;
    
      get _address(): Address {
        return new Address();
      }
     
    }
Onur Dikmen
  • 339
  • 1
  • 6
  • 17
6

In my case it works with different declaration according new typescript strict features:

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

If disable typescript new strict feature in tsonfig.json with

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

the old Angular's guide code works well

@ViewChild(MatSort) sort: MatSort;

Here is 4 ways to solve the issue thanks to Arunkumar Gudelli (2022) https://www.angularjswiki.com/angular/property-has-no-initializer-and-is-not-definitely-assigned-in-the-constructor/

Alexey Ryzhkov
  • 411
  • 4
  • 10
4

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

I think this recommendation from angular gives good advice:

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 a).
  • Fields that have an initializer, but it lives in ngOnInit and cannot be moved because it depends on other @input fields - Add back '!' - c).
Nate Anderson
  • 18,334
  • 18
  • 100
  • 135
maxisam
  • 21,975
  • 9
  • 75
  • 84
2

Add these two line on the tsconfig.json

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

and make sure strict is set to true

Sydney_dev
  • 1,448
  • 2
  • 17
  • 24
2

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,
}
Tabish Zaman
  • 227
  • 3
  • 4
1

change the

fieldname?: any[]; 

to this:

fieldname?: any; 
Abilogos
  • 4,777
  • 2
  • 19
  • 39
MAM.AASIM
  • 29
  • 2
1

You can declare property in constructor like this:

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

myText: string ;
}
keivan kashani
  • 1,263
  • 14
  • 15
0

Follow 2 steps to solve this::

  1. "strictPropertyInitialization": false entry in tsconfig.json
  2. ctrl+c stop your server on Terminal(check for terminal, where it is running) and run it again with the command you use like ng serve These 2 steps, should solve your issue.. as it solved mine.. cheers.. ;)
0

Instead of turning off the strict mode, you can assign a initial value to the variable. For example:

  1. makes: any[] = [null];

  2. private year: number = 0;

0

A little late for the party. but the most voted answer includes changing the security level as a whole abandoning type safety, to work around this use the typing mechanism of the typescript itself

@ViewChild(MatPaginator) paginator: MatPaginator | undefined;

ngAfterViewInit() { 
  this.dataSource.paginator = this.paginator as MatPaginator;
}

I believe the angular material documentation should be updated, but until then I believe this is the best way to do it

-2

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

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

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

Suresh
  • 477
  • 4
  • 8
-3

Just declare your variable as type any

@Input() headerName: any;
-4

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

Example:

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