typescript构建:运算符'=='不能应用于类型'“=”'和'“{”'

问题描述 投票:1回答:2

我遇到了这个有趣的编译错误,在我看来,Typescript对于它自己的好处太聪明了。

private _currentToken: string;
....
private ParseKeyValuePair(): KeyValuePair<string, any>
{
    let key = this.RemoveBracketAndQuote(this._currentToken);
    this.NextToken();
    if (this._currentToken != "=")
        throw "Expect = sign but got " + this._currentToken;

    this.NextToken();
    let val: any = this.RemoveBracketAndQuote(this._currentToken);
    if (this._currentToken == "{") //Compile error on this line
        val = this.ParseObject();

    return new KeyValuePair(key, val);
}

这是我编写的一个快速而脏的解析器,当使用TS 1.7编译时,它运行得非常好

我将TS升级到2.6后,我收到了这个编译错误。

构建:运算符'=='不能应用于键入'“=”'和'“{”'

对我来说似乎TS看到第一个if语句并确定this._currentToken必须是字符串"="否则将抛出异常。但事实上this._currentToken会因this.NextToken()电话而改变,TS也没有预料到这一点。

它是一个Typescript编译器错误还是我在这里做了一些愚蠢的事情?

编辑:我能够做一个最小的可重复的例子

class Test
{
    private property: string;

    private changeProperty(): void
    {
        this.property = "bar";
    }

    private TestFunc(): void
    {
        if (this.property != "foo")
            throw "bad";

        this.changeProperty();
        if (this.property == "bar") //compile error
            console.log("good");
    }
}
typescript typescript2.0
2个回答
2
投票

这是一个打字稿功能,虽然在这种情况下它看起来比它有帮助更疼。 Typescript有一个“类型缩小”的概念,如果你沿着某些代码路径限制变量类型,typescript将使用更窄的类型。所以对于你的代码片段,行:

if (this._currentToken != "=")
    throw "Expect = sign but got " + this._currentToken;

意味着如果当前令牌是除了值"="之外的任何东西,那么该方法将抛出并且代码将不会超过该值。因此,如果代码HAS超过该代码,则该值必须为"="。换句话说,该行代码已将您的类型缩小为字符串文字“=”。

然后你有线:

if (this._currentToken == "{") //Compile error on this line
    val = this.ParseObject();

这会产生错误,因为打字稿相信你的this._currentToken的值为"=",它不等于"{"。所以(在打字稿中),这个if语句总是假的,它想省你一些麻烦。

问题是你调用了一个方法nextToken,我假设它改变了_.currentToken值。可悲的是,打字稿并没有意识到这一点。

所以你有几个选择

  • 你可以添加一条评论://@ts-ignore就在违规行的正上方,以便打印出打字稿。
  • 您可以将值转换为字符串,例如:if ((this._currentToken as string) == "{") ...

无论哪种方式,你都必须手动给打字稿提示它的推断不太正确。


1
投票

您可以使用类型保护来通知类型系统您正在描述的更改:

class Test
{
    property: string;

    private changeProperty(): this is this & { property: "bar" }
    {
        this.property = "bar";
        return true;
    }

    private TestFunc(): void
    {
        if (this.property != "foo")
            throw "bad";

        if (this.changeProperty()) {
            if (this.property == "bar") // no compile error
                console.log("good");
        }
    }
}

它有点hacky,但它的工作原理。

© www.soinside.com 2019 - 2024. All rights reserved.