2017-11-30 29 views
1

私のクラスの引数の1つに文字列またはエラーを受け入れることができるようにしたいが、インライン条件を使用して型をチェックするときに型がガードされるようにする。インライン条件付き型ガード

以下の3つの例から明らかなように、インライン条件の型ガードはサポートされていないようですが、最後のものだけがコンパイルされます。これは、よりである:何らかの理由でdocumentation

UPDATEで「インライン」と呼ばれている

私は「インライン条件文」と言うとき、私は/他のブロック場合は複数行ない、フォーム(<boolean statement>)? a : bの意味、活字体が適切に三元の文で使用されるタイプのガードを処理しない正しく

export class MyError extends Error { 
    public code; name; message 

    constructor(code: number = -1, name: string = '', err?: Error | string) { 
     super() 
     this.name = name 
     this.code = code 
     // no type guards 
     this.message = this.name + (err)? ": " + (err instanceof Error)? err.message : err : '' 
    } 
} 

export class MyError2 extends Error { 
    public code; name; message 

    constructor(code: number = -1, name: string = '', err?: Error | string) { 
     super() 
     this.name = name 
     this.code = code 
     if(err) { 
      // no type guards 
      this.message = this.name + ": " + (err instanceof Error)? err.message : err 
     } else { 
      this.message = this.name 
     } 
    } 
} 

export class MyError3 extends Error { 
    public code; name; message 

    constructor(code: number = -1, name: string = '', err?: Error | string) { 
     super() 
     this.name = name 
     this.code = code 
     // type guards... but at what cost to brevity 
     this.message = this.name 
     if(err) { 
      if(err instanceof Error) { 
       this.message += ": " + err.message 
      } else { 
       this.message += ": " + err 
      } 
     } 
    } 
} 
+1

あるerr.messageerrかどうかを評価します:err'が受け入れる' <にErrorMessage> 'とエラーオブジェクトまたはエラーメッセージが表示された場合は、行を 'this.message = \' $ {this.name}と書くことができます:$ {err.message ||エラー} \ ';'。また、あなたのタイプは 'エラー:エラー:文字列'ではないでしょうか? ** String!== string ** – Rajesh

+0

私はそれが好きです。唯一のことは、 'err'が定義されていない場合、 ":"を持たないことです。ですから、タイプを 'Error |文字列| strictNullChecksが有効であると仮定して、「null」となります。更新された文字列の場合、歓声。 –

答えて

1

インライン条件文のサポートタイプのガードをしtypescriptですよりjavascriptの、で行います。括弧を使用すると、これらのステートメントで予想される動作とは異なる動作になります。

export class MyError extends Error { 
    public code; name; message 

    constructor(code: number = -1, name: string = '', err?: Error | String) { 
     super() 
     this.name = name 
     this.code = code 
     this.message = this.name + (err ? ": " + (err instanceof Error ? err.message : err) : '') 
    } 
} 

export class MyError2 extends Error { 
    public code; name; message 

    constructor(code: number = -1, name: string = '', err?: Error | String) { 
     super() 
     this.name = name 
     this.code = code 
     if(err) { 
      this.message = this.name + ": " + (err instanceof Error ? err.message : err) 
     } else { 
      this.message = this.name 
     } 
    } 
} 

は、私はまた、括弧内の全体の三元の文を囲むことはそれをより読みやすく役立つと信じているが、それは個人の意見の問題です:あなたが最初の2つの例では、このようなコードをフォーマットすると、すべてが正常に動作するはずですコース。


あなたの3者声明には何が問題なのですか? operator precedence rulesのため、最初の?の左にあるものはすべて同じ式の一部であり、したがってすべてが一緒に連結され、3項の全体の意味を変更します。ここでは例です:

this.message = this.name + ": " + (err instanceof Error)? err.message : err 
// same as: 
(this.name + ": " + (err instanceof Error)) ? err.message : err 
// with values filled in: 
"someName: true" ? err.message : err 

だから、上記のコードは、常にあなたが `としてあなたのメッセージをしたいと仮定すると、 Error

+0

うん、ちょうど純粋なjavascriptでチェックし、問題は文字列の連結である。私たちが 'a =" a: "+(false)に行くとIE? "a":(false)? "b": "c" 'a"を得るが、 'a = \' a:$ {(false)? "a":(false)? "b": "c"} \ ''、 "a:c"を期待どおりに取得します。タイスクリプトの問題ではないようです。 –

+1

はい、正確です。 [演算子優先ルール](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence)のために、最初の '? 'の左にあるものはすべて同じものの一部ですしたがって、すべてが一緒に連結され、三項の全体的な意味が変わります。 – JKillian

+0

これは素晴らしいです: 'this.message = \' $ {this.name} $ {(err)? ":" :(エラーのエラー)? err.message:err} \ ''、最初の例でこれを使って答えを更新してもよろしいですか?それを受け入れるでしょう - あとで読んでいる人にとって混乱は少なくなります。すなわち、それを動作させるためにブラケット加工が必要ないことを実証する。 –