型推論(かたすいろん、英: type inference)とはプログラミング言語の機能の1つで、静的な型付けを持つ言語において、変数や関数シグネチャの型を明示的に宣言しなくても、変数宣言における初期化のための初期値や、関数呼び出しにおける実引数などといった、周辺情報および文脈などから自動的に(暗黙的に)各々の型を決定する機構のこと。言語によってはtype deductionと呼ばれることもある。
推論に失敗するとその時点でエラーを報告できるため、少なくとも誤った型を用いることによるバグは回避できる。また、アルゴリズムの記述に集中できるのでプログラムの抽象度が上がるというメリットもある。型名が長大な場合に、型推論による省略によってコード全体の見通しをよくすることにもつながるが、一方で統合開発環境による支援(コードエディター上のツールチップなど)が得られない環境では、一見して型が分からないことでコードレビューがしにくくなるというデメリットもある。
代表的な型推論アルゴリズムとして、Hindley/Milner 型推論アルゴリズムがある。各々著名なコンピュータ科学者の名前からつけられた名前であるが、Hindley は論理学者として型推論システムを先に開発した。
型推論を持つ言語としてはHaskell、ML、Vala、OCaml、F#、C#、Java、Scala、C++、D言語、Concurrent Clean、Swiftなどがある。静的型付け関数型プログラミング言語のほとんどがなんらかの型推論の機能を持っている。登場当初は型推論を持っていなかった言語であっても、関数型言語に影響を受けた拡張や改訂により型推論の機能を持つようになった言語も多い。
ただし型推論と関数の多重定義(オーバーロード)は相性が悪く、オーバーロードをサポートする言語では型推論による恩恵が十分に受けられない(型推論ではシグネチャを一意に決めることができない)ケースがある。 この節では型推論の構文解析理論には踏み込んでいない。 ほとんどの言語においては、関数の仮引数および戻り値、演算子のオペランドおよび結果、変数、そしてそれらから成る式は、各々が保持するデータの種類を表す型を持つ。構文上で明らかな名前を持つ型による区別をしない言語であっても、内部的にはなんらかの型を持っていて区別しているケースが多い。実行時に型が決まる言語を動的型付けの言語という。一方、コンパイル時に型が決まる言語を静的型付けの言語という。静的型付けの言語において、関数の仮引数および戻り値の型や変数の型は、通常は明示的に記述する必要がある。例えば、次はC言語の例である[1]。int addone(int x) { int result; result = x + 1; return result;} 関数定義の最初の行int addone(int x)では、関数addoneは整数一つを入力引数として受け取り、整数を出力結果として返す、と宣言している。int result;の行では、ローカル変数resultが整数型であることを宣言している。 上記の例にほぼ1対1で対応するコードを、F#を使って記述すると下記のようになる。let addone (x : int) : int = let result : int = x + 1 result しかしF#は型推論の機能を持っているため、次のように書くこともできる。let addone x = let result = x + 1 result このF#の例において、 という仕様であり、右オペランドには整数リテラル1が記述されていることから、左オペランドの変数xすなわち関数の引数xも同じ整数型であるということが推論される。
具体例による説明
2項演算子+の左オペランドと右オペランドの型は同じであり、演算結果は同じ型を返す。