打字稿错误:在分配之前使用了属性

Loc*_*ost 4 typescript

打字稿显示[ts]在 VSCode中分配之前使用了属性“记录器”。错误发生在下面的代码中this.logger.logInfo(Important, ...。我很清楚地在构造函数的第二行设置了这个属性,所以......?

如果我使用self代码中显示的var (self.logger.logInfo...),TS 错误就会消失,但这不是必需的。

感谢您分享您的专业知识:-)

// app/data/mongo/_base.data.mongo.ts 

import { MongoClient, ObjectId } from 'mongodb';
import { IBaseModel } from '../../model/_base.model';
import { Logger, Important, NotImportant } from '../../util/logger';

export default class BaseData {

    constructor(params: any) {
        this.collectionName = params.collectionName;
        this.logger = new Logger(this.collectionName);
        if (this.db) {
            this.collection = this.db.getCollection(this.collectionName);
        } else {
            BaseData.userId = params.user.id;
            BaseData.userHandle = params.user.handle;
            this.dbServer = params.dbServer;
            this.dbPort = params.dbPort || '27017';
            this.dbName = params.dbName;
            const self = this; // This is a Typescript BUG!
            (async () => {
                const url = `mongodb://${this.dbServer}:${this.dbPort}`;
                this.db = await MongoClient.connect(url, { "useNewUrlParser": true });
                this.collection = this.db.collection(this.collectionName);
                this.logger.logInfo(Important, 'contructor', `MongoDb connection (${url}) success!`);
            })();
        }
    }

    static userId: string;
    static userHandle: string;

    protected logger: Logger;
    protected collectionName: string = '';
    protected client: any;
    protected collection: any;
    protected db: any;
    protected dbServer: string = '';
    protected dbPort: string = '';
    protected dbName: string = '';
Run Code Online (Sandbox Code Playgroud)

jca*_*alz 6

这是一些重现该问题的自包含代码:

// Turn on --strictNullChecks and --strictPropertyInitialization
class Foo {
    prop: string;
    constructor() {
        this.prop = "assigned";
        (async () => {
            this.prop; // error, used before assigned
        })();
    }
}
Run Code Online (Sandbox Code Playgroud)

在 Playground 上查看(记得打开--strictNullChecks--strictPropertyInitialization编译选项)。


这很可能是 TypeScript 的设计限制,如果不是一个成熟的错误。事实是,自动化控制流分析很难做到“正确”。由于编译器通常不可能准确找出程序中每个点的每个变量可能的状态,因此它必须使用启发式方法,这往往会导致误报(未捕获的错误)和误报(未捕获的错误)。错误)。这对我来说似乎是一个误报,因为在this.prop设置之后肯定会调用异步函数。 之前已经提出并解决了类似的问题,即同步立即调用函数表达式。

我认为需要有人更了解 TypeScript 如何进行控制流分析的细节才能在这里权威地发言,但我猜测这种特殊情况并没有被预期或遇到足以处理它。如果你认为你有一个引人注目的用例,你可能想在 GitHub 中提交一个问题,假设没有人对这个问题提供更令人满意的答案。

同时,如果您有解决方法,例如分配const self = this然后访问self.prop,或等效访问(this as this).prop,那么我想您应该使用它。并且总是有所有变通方法的大锤,//@ts-ignore评论

class Foo {
  prop: string;
  constructor() {
    this.prop = "assigned";
    (async () => {
      // @ts-ignore: this.prop is really assigned before being used
      this.prop;
    })();
  }
}
Run Code Online (Sandbox Code Playgroud)

哦,对不起,我没有更好的消息。希望在任何情况下都有帮助。祝你好运!