简体   繁体   中英

Strict Class Initialization in Typescript 2.7

So I created a sample project using the Visual Studio 2017 template 'ASP.NET Core Web Application' with Angular. I updated the package.json created by default to the latest modules' versions. After running the npm install command and launching the site I get and error related to TypeScript.

ERROR in [at-loader] ./ClientApp/app/components/fetchdata/fetchdata.component.ts:9:12 TS2564: Property 'forecasts' has no initializer and is not definitely assigned in the constructor.

Angular is running in the development mode. Call enableProdMode() to enable the production mode. client.js:67 [HMR] connected client.js:160 [HMR] bundle has 1 errors client.js:161 [at-loader] ./ClientApp/app/components/fetchdata/fetchdata.component.ts:9:12 TS2564: Property 'forecasts' has no initializer and is not definitely assigned in the constructor.

The error is quite clear. I researched a little bit and found out a new feature for the TS 2.7: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html

Strict Class Initialization

TypeScript 2.7 introduces a new flag called --strictPropertyInitialization. This flag performs checks to ensure that each instance property of a class gets initialized in the constructor body, or by a property initializer. For example ...

This is the code where the error appears

import { Component, Inject } from '@angular/core';
import { Http } from '@angular/http';

@Component({
    selector: 'fetchdata',
    templateUrl: './fetchdata.component.html'
})
export class FetchDataComponent {
    public forecasts: WeatherForecast[];

    constructor(http: Http, @Inject('BASE_URL') baseUrl: string) {
        http.get(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => {
            this.forecasts = result.json() as WeatherForecast[];
        }, error => console.error(error));
    }
}

interface WeatherForecast {
    dateFormatted: string;
    temperatureC: number;
    temperatureF: number;
    summary: string;
}

And this is my tsconfig.json file

{
  "compilerOptions": {
    "module": "es2015",
    "moduleResolution": "node",
    "target": "es5",
    "sourceMap": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "skipDefaultLibCheck": true,
    //"skipLibCheck": true, // Workaround for https://github.com/angular/angular/issues/17863. Remove this if you upgrade to a fixed version of Angular.
    "strictPropertyInitialization": false,
    "strict": false,
    "lib": [ "es6", "dom" ],
    "types": [ "webpack-env" ]
  },
  "exclude": [ "bin", "node_modules" ],
  "atom": { "rewriteTsconfig": false }
}

Then the VS intellisense doesn't complain but the error is still there when running.

I have also tried to define the forecasts field with public forecasts: WeatherForecast[]; but it didn't help

Node v9.9.0 TypeScript 2.7.2 Angular 5.2.9

You should define the field as being optional, as there will be a time interval between the constructor call and until you get the result of get that the field will be null . This does mean you will have to check that the field is not null where you use the field, but this is probably a good idea:

export class FetchDataComponent {
    public forecasts?: WeatherForecast[];
    // equivalent to: 
    // public forecasts: WeatherForecast[] | undefined;
    doStuff(){
        this.forecasts.push() // error Object is possibly 'undefined'
        if(this.forecasts != null) {
            this.forecasts.push(); // ok 
        }
        this.forecasts!.push() // We tell the compiler we know better and not to complain about Object is possibly 'undefined'
    }
}

Another option is to use the definite assignment assertion ( ! ) which will tell the compiler the field will be initialized and will definitely not be null (a lie in this case). This exposes you to some runtime errors, but you will not need to check the fields on usage. I don't recommend this in this case, but it is your call:

export class FetchDataComponent {
    public forecasts!: WeatherForecast[];
    doStuff(){
        this.forecasts.push() // ok
        if(this.forecasts != null) {
            this.forecasts.push(); // ok too
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM