Typescript 2.7中的严格类初始化

6

所以我使用Visual Studio 2017模板“ASP.NET Core Web Application”和Angular创建了一个示例项目。 我将默认创建的package.json更新到了最新的模块版本。 运行npm install命令并启动网站后,我遇到了与TypeScript相关的错误。

[at-loader] ./ClientApp/app/components/fetchdata/fetchdata.component.ts:9:12出现错误 TS2564: 属性'forecasts'没有初始化程序,并且在构造函数中未被明确定义。

Angular正在开发模式下运行。调用enableProdMode()以启用生产模式。 client.js:67 [HMR]已连接 client.js:160 [HMR]捆绑包有1个错误 client.js:161 [at-loader] ./ClientApp/app/components/fetchdata/fetchdata.component.ts:9:12 TS2564: 属性'forecasts'没有初始化程序,并且在构造函数中未被明确定义。

错误很明显。我做了一些研究,发现了TS 2.7的一个新特性: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html 严格类初始化 TypeScript 2.7引入了一个名为--strictPropertyInitialization的新标志。此标志执行检查以确保类的每个实例属性在构造函数体内或通过属性初始化器进行初始化。例如...
这是出现错误的代码。
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;
}

这是我的tsconfig.json文件。

{
  "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 }
}

然后,VS智能感知不会抱怨,但运行时仍然存在错误。

我还尝试使用public forecasts: WeatherForecast[];定义forecasts字段,但没有帮助。

Node v9.9.0 TypeScript 2.7.2 Angular 5.2.9

1个回答

5

应该将字段定义为可选的,因为在构造函数调用和获取get结果之间会有一个时间间隔,此时字段将为null。这意味着您需要在使用该字段的地方检查该字段是否为null,但这可能是一个好主意:

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

另一个选项是使用明确的赋值断言 (!) 告诉编译器该字段将被初始化并且绝对不会为 null(在这种情况下是虚假的)。这样会暴露你到一些运行时错误,但你在使用时就不需要检查这些字段了。在这种情况下我不建议使用,但这是你的决定:

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

或者他可以尝试: 公共预测: WeatherForecast[] | undefined; - rrd
1
@rrd 是的,但这只是一种更冗长的写法,等同于 public forecasts?: WeatherForecast[]。如果你在这个声明上悬停到 forecast 上面,你会看到类型实际上是 WeatherForecast[] | undefined - Titian Cernicova-Dragomir
@rrd添加了你的版本以保证完整性,非常感谢 :) - Titian Cernicova-Dragomir
1
我会给这个答案点赞,覆盖了所有可能性。 - rrd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接