比较可变枚举成员变量时的Typescript编译器错误

时间:2017-10-11 09:00:06

标签: typescript enums

我收到错误:

TS2365: Operator '===' cannot be applied to types 'ExampleState.Unsaved' and 'ExampleState.Saving'.

将枚举与可变成员变量进行比较时:

enum ExampleState {
    Unset = -1,
    Unsaved = 0,
    Saving = 1,
    Saved = 2
}

class Example {

    private state : ExampleState = ExampleState.Unset;

    public Save() {
        if (this.state === ExampleState.Unsaved) {
            this.BeginSaving();
            while (this.state === ExampleState.Saving) {  // !error!
                this.CommitSave();
            }
        }
    }

    private BeginSaving() {
        this.state = ExampleState.Saving;
    }

    private CommitSave() {
        this.state = ExampleState.Saved;
    }
}

真正的例子是一个执行多次保存尝试的异步方法 -  这已被简化为只是说明错误。

Typescript似乎并不明白这个变量是可变的,并且过于积极地假设它没有被改变。为什么会发生这种情况以及解决方法是什么?

2 个答案:

答案 0 :(得分:2)

这是know issus from the Control flow analysis

作为another workaround,您可以为state属性创建包装器方法。 (谢谢@Paleo)

访问Playground

enum ExampleState {
    Unset = -1,
    Unsaved = 0,
    Saving = 1,
    Saved = 2
}

class Example {

    private state : ExampleState = ExampleState.Unset;

    private State() { 
        return this.state;
    }

    public Save() {
        if (this.State() === ExampleState.Unsaved) {
            this.BeginSaving();
            while (this.State() === ExampleState.Saving) { 
                this.CommitSave();
            }
        }
    }

    private BeginSaving() {
        this.state = ExampleState.Saving;
    }

    private CommitSave() {
        this.state = ExampleState.Saved;
    }
}

答案 1 :(得分:0)

它正在发生,因为ExampleState.Unsaved不仅是值,而且是类型(let x: ExampleState.Unsaved在语义上有效)。打字稿有所谓的打样,你的

if (this.state === ExampleState.Unsaved)

语句就是这种保护 - 在该语句中,typescript假定this.state始终是ExampleState.Unsaved的类型。

我怀疑枚举类型实际上只是作为联合类型处理,所以你的代码等同于(它也不起作用):

type ExampleState = -1 | 0 | 1 | 2;
class Example {

    private state : ExampleState = -1;

    public Save() {
        if (this.state === 0) {
            this.BeginSaving();
            while (this.state === 1) {  // !error!
                this.CommitSave();
            }
        }
    }

    private BeginSaving() {
        this.state = 1;
    }

    private CommitSave() {
        this.state = 2;
    }
}

正如@Paleo所说,我认为值得提交给TypeScript团队(如果尚未由其他人发送)。目前,我建议在while语句中输入类型。与使用while的解决方案相比,它产生的JavaScript输出与您最初想要的完全相同。

while (this.state as ExampleState === ExampleState.Saving) {  // no error
    this.CommitSave();
}