TypeScriptでは、明示的な型注釈がない場合に型情報を提供するために、型推論がいくつかの場面で使用されます。例えば、以下のコードでは
tsTry
letx = 3;
x
変数の型はnumber
と推論されます。この種の推論は、変数とメンバーの初期化、パラメータのデフォルト値の設定、関数の戻り値の型の決定時に行われます。
ほとんどの場合、型推論は簡単です。以下のセクションでは、型がどのように推論されるかについて、いくつかのニュアンスを探ります。
最良の共通型
複数の式から型推論を行う場合、それらの式の型を使用して「最良の共通型」が計算されます。例えば、
tsTry
letx = [0, 1, null];
上記の例でx
の型を推論するには、各配列要素の型を考慮する必要があります。ここでは、配列の型としてnumber
とnull
の2つの選択肢が与えられています。最良の共通型アルゴリズムは、各候補型を検討し、他のすべての候補と互換性のある型を選択します。
最良の共通型は、提供された候補型から選択する必要があるため、型は共通の構造を共有するものの、どの型もすべての候補型のスーパータイプではない場合があります。例えば
tsTry
letzoo = [newRhino (), newElephant (), newSnake ()];
理想的には、zoo
がAnimal[]
と推論されることが望ましいですが、配列内に厳密にAnimal
型のオブジェクトがないため、配列要素の型については推論を行いません。これを修正するには、どの型も他のすべての候補のスーパータイプでない場合に、明示的に型を指定します。
tsTry
letzoo :Animal [] = [newRhino (), newElephant (), newSnake ()];
最良の共通型が見つからない場合、結果の推論はユニオン配列型である(Rhino | Elephant | Snake)[]
になります。
コンテキスト型付け
TypeScriptでは、場合によっては型推論が「逆方向」にも機能します。これは「コンテキスト型付け」と呼ばれます。コンテキスト型付けは、式の型がその場所によって暗示される場合に発生します。例えば
tsTry
window .onmousedown = function (mouseEvent ) {console .log (mouseEvent .button );Property 'kangaroo' does not exist on type 'MouseEvent'.2339Property 'kangaroo' does not exist on type 'MouseEvent'.console .log (mouseEvent .); kangaroo };
ここで、TypeScript型チェッカーは、`Window.onmousedown`関数の型を使用して、代入の右辺にある関数式の型を推論しました。そうすることで、MouseEvent型の`mouseEvent`パラメータの型を推論することができ、これには`button`プロパティは含まれていますが、`kangaroo`プロパティは含まれていません。
これは、windowがすでに型で`onmousedown`を宣言しているため機能します。
ts
// Declares there is a global variable called 'window'declare var window: Window & typeof globalThis;// Which is declared as (simplified):interface Window extends GlobalEventHandlers {// ...}// Which defines a lot of known handler eventsinterface GlobalEventHandlers {onmousedown: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null;// ...}
TypeScriptは、他のコンテキストでも型を推論するのに十分なほどスマートです。
tsTry
window .onscroll = function (uiEvent ) {Property 'button' does not exist on type 'Event'.2339Property 'button' does not exist on type 'Event'.console .log (uiEvent .); button };
上記の関数が`Window.onscroll`に代入されているという事実から、TypeScriptは`uiEvent`がUIEventであり、前の例のようなMouseEventではないことを認識しています。`UIEvent`オブジェクトには`button`プロパティが含まれていないため、TypeScriptはエラーをスローします。
この関数がコンテキスト型付けされた位置にない場合、関数の引数は暗黙的にany
型となり、エラーは発生しません(noImplicitAny
オプションを使用している場合を除く)。
tsTry
consthandler = function (uiEvent ) {console .log (uiEvent .button ); // <- OK};
コンテキスト型をオーバーライドするために、関数の引数に明示的に型情報を指定することもできます。
tsTry
window .onscroll = function (uiEvent : any) {console .log (uiEvent .button ); // <- Now, no error is given};
ただし、uiEvent
にはbutton
というプロパティがないため、このコードはundefined
をログに記録します。
コンテキスト型付けは多くの場合に適用されます。一般的なケースとしては、関数呼び出しの引数、代入の右辺、型アサーション、オブジェクトおよび配列リテラルのメンバー、return文などがあります。コンテキスト型は、最良共通型における候補型としても機能します。例えば、
tsTry
functioncreateZoo ():Animal [] {return [newRhino (), newElephant (), newSnake ()];}
この例では、最良共通型には4つの候補があります。Animal
、Rhino
、Elephant
、およびSnake
です。これらのうち、最良共通型アルゴリズムによってAnimal
が選択されます。