TypeScriptでは関数の型定義のやり方がいくつかあり、よく理解できていなかったのでまとめてみます。
型定義の書き方
関数の型定義は2種類の書き方が存在します。
省略記法
省略記法では(引数の型) => 戻り値の型
の形式で記述します。
アロー関数と同じような書き方です。
type Example1 = (param: string) => string;
const example1: Example1 = param => param;
example1は型Example1
の型アノテーションをつけて、関数を定義しています。
型アノテーションによって関数の引数が推論され、引数のparam
はstring
型と解釈されます。
完全記法
完全記法では(引数の型): 戻り値の型
という組を{}
の中に記述します。
type Example2 = {
(param: string): string;
}
const example2: Example2 = param => param;
型定義のExample2
とExample1
は全く同じ意味になります。
関数のオーバーロード
完全記法では{}
の中に複数の(引数の型): 戻り値の型
を記述できます。
その場合はオーバーロードを意味します。
type Example3 = {
(): string;
(param: string): string;
(param: number): string;
}
const example3: Example3 = (param?: string | number) => `${param}`;
example3.ts
に定義された型Example3
を見ると戻り値はすべてstringです。
一方、第一引数は型はundefined,string,number
の3種類が定義されています。
この場合、第一引数の型は3種類のいずれかであると解釈されます。
すなわちparams
の型はundefined | string | number
になります。
example3.ts
を省略記法で書くとexample4.ts
のようになります。
type Example4 = (param?: string | number) => string
const example4: Example4 = (param?: string | number) => `${param}`;
ジェネリクスの使い方
省略記法
省略記法の場合、ジェネリクスは関数の引数の前に<>
で囲んで定義します。
type Example5 = <T>(param: T) => T;
const example5: Example5 = param => param;
typeの変数名の右側にも書くことが可能です。
この場合は型アノテーションでジェネリクスの型を定義する必要があります。
type Example6<T> = (param: T) => T;
const example6: Example6<number> = (param) => param;
// 以下はエラー
// const example6: Example6 = (param) => param;
完全記法
完全記法の場合も省略記法と同様に関数の引数の前に<>
で囲んでジェネリクスを定義します。
type Example7 = {
(): string;
<T>(param: T): string;
}
const example7: Example7 = (param?: number) => `${param}`;
typeの変数名の右側に書くことも可能です。
この場合は、複数の(引数の型): 戻り値の型
に適用できます。
type Example8<T> = {
(): T;
(param: string): T;
(param: number): T;
}
const example8: Example8<string> = (param?: string | number) => `${param}`;