2017-12-28 18 views
1

Typescriptが自分の利益のためにあまりにもスマートであると思われるこの面白いコンパイルエラーが発生しました。typescriptビルド:オペレータ '=='は入力できません '' = "'and'" {"'

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); 
} 

これは私が書いた迅速かつ汚いパーサであり、私は私がこのコンパイルエラーを取得しています2.6にTSをアップグレードした後、TS 1.7

でコンパイルしたとき、それは完璧に動作します。 TSは、最初のif文を見て、それを決定するようにそれはそう私には演算子「==」は型に適用されるカント「『=』」と「『{』」

this._currentToken

ビルド文字列"="でなければなりません。それ以外の場合は例外がスローされます。しかし実際にはthis._currentTokenthis.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"); 
    } 
} 

答えて

2

最小再現可能な例を作ることができていますこれは、typescriptです機能です。 Typescriptには「型絞り込み」というコンセプトがあります。ここでは、コードパスに沿って変数型を制限すると、typescriptはその狭められた型をその行の下側で使用します。だからあなたのスニペットのために、行:

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

は、現在のトークンが値"="以外のものであれば、この方法はスローされますと、コードがそれを過ぎて進まないことを意味します。したがって、コードHASがそれを超えて進む場合、値は"="でなければなりません。言い換えれば、そのコード行はあなたの型を文字列リテラル "="に絞り込んでいます。

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

typescriptですが、あなたのthis._currentToken"{"と等しくない値"="を、持っていると考えているため、エラーが発生します。

その後、ラインを持っています。だから(typescriptの考え方では)、このif文は常にfalseで、あなたにいくつかの問題を救いたい。

問題は、nextTokenというメソッドを呼び出すことです。これは、_.currentTokenの値を変更するものと想定しています。残念ながらタイトスクリプトはそれを認識していません。

だからあなたはあなたがコメントを追加することができますいくつかのオプション

  • を持っている:typescriptですが黙秘権問題のある行の上//@ts-ignoreを。
  • あなたは、文字列、例えばとしてあなたの値をキャストすることができますif ((this._currentToken as string) == "{") ...

いずれかの方法を、手動でtypescriptですにそれの推論はかなり右でないことをヒントを与える必要があります。

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"); 
     } 
    } 
} 

それは少しハックだが、それは動作します。

関連する問題