型推論

TypeScriptは、いくつかの簡単なルールに基づいて変数の型を推論(およびチェック)します。これらのルールはシンプルなので、安全/安全でないコードを認識するために、脳に記憶することができます(これは私と私のチームメイトでは非常にすぐでした)。

型の流れは、私が頭の中で想像する型情報の流れとちょうど一致しています

変数の定義(Variable Definition)

変数の型は、定義によって推論されます。

let foo = 123; // foo is a `number`
let bar = "Hello"; // bar is a `string`
foo = bar; // Error: cannot assign `string` to a `number`

これは右から左に流れる型の例です。

関数の戻り値の型(Function Return Types)

戻り値の型は、return文によって推測されます。次の関数はnumberを返すと推測されます。

function add(a: number, b: number) {
    return a + b;
}

これは底から流れ出ていく型の例です。

代入(Assignment)

関数のパラメータ/戻り値の型は、代入によっても推論することができます。fooAdderで、numberabの型になります。

この事実は、以下のコードで示すことができます。あなたが期待する通りのエラーが発生します:

これは、左から右に流れる型の例です。

コールバック引数の関数を作成する場合、同じ代入スタイルの型推論が機能します。結局のところ、argument -> parameterは単に変数代入の一種です。

構造化(Structuring)

これらの単純なルールは、構造化(オブジェクトリテラルの作成)の下でも機能します。たとえば、次のような場合、fooの型は{a:number, b:number}と推論されます。

同様に配列について:

そしてもちろんどんなネストでも:

分解(Destructuring)

そしてもちろん、構造の分解でも機能します:

配列:

関数のパラメータの型が推測できれば、その構造化されたプロパティも同様に推測されます。例えばここでは引数をa/bのメンバに分解します。

Type Guard (Type Guards)

Type Guardが(特にユニオン型の場合に)どのように型を変更したり絞り込んだりするのかを見てきました。TypeGuardは、ブロック内の変数の型推論の別の形式です。

警告(Warnings)

パラメータに注意してください

代入から推論できない場合、型は関数パラメータに流れません。たとえば次のような場合、コンパイラはfooの型を知らないので、abの型を推論することはできません。

しかし、 fooに型を指定された場合、関数パラメータの型を推論することができます(以下の例ではabは両方ともnumber型であると推測されます)。

returnに注意してください

TypeScriptは一般的に関数の戻り値の型を推測することができますが、期待通りではない可能性があります。例えば、ここでは関数fooanyの戻り値の型を持っています。

これは、addOneの型定義が悪いため、fooの戻り値の型が影響を受けたものです(aanyなのでaddOneの戻り値はanyで、fooの戻り値はany)。

関数の返り値を明示するのが最も簡単だと分かります。結局のところ、これらのアノテーションは定理であり、関数本体が証明です。

想像できる他のケースもありますが、良いニュースは、そのようなバグを捕まえるのに役立つコンパイラフラグがあることです。

noImplicitAny

フラグ noImplicitAnyは、変数の型を推測できない場合(したがって、暗黙のany型としてしか持つことができない場合)、エラーを発生させるようにコンパイラに指示します。それによって、次のことが可能です。

  • そうしたい場合は、明示的に:any型の注釈を加えることでany型にしたい

  • 正しいアノテーションを追加することによってコンパイラを助ける

最終更新

役に立ちましたか?