TL;DR
- 関数式を使うと、関数全体に関数型を適用できる。
- 関数型を使うと繰り返しが減り、型と実装を分けられ、
typeof fetchのように他の関数のシグネチャにも合わせられる。
内容
関数文と関数式
関数は、関数文でも関数式でも定義できる。
function rollDice(sides: number): number { ... } // 関数文
const rollDice = function (sides: number): number { ... }; // 関数式
const rollDice = (sides: number): number => { ... }; // 関数式関数式を使うと、関数全体に対して型宣言(関数型)を適用できる。
type DiceRollFn = (sides: number) => number;
const rollDice: DiceRollFn = (sides) => { ... };関数型を使う利点
1 つ目の利点は、繰り返しを減らせることである(DRY)。ライブラリを提供するなら、よく使うコールバックの型宣言を提供するとよい。
2 つ目は、型と関数の実装を切り離すことで、ロジックを明確にできることである。
3 つ目は、他の関数のシグネチャに合わせられることである。たとえば、レスポンスのステータスをチェックする fetch を作るとする。シグネチャは次のように書けるが、
async function checkedFetch(input: RequestInfo, init?: RequestInit) { ... }関数型を適用すると、より簡潔に書ける。
const checkedFetch: typeof fetch = async (input, init) => { ... };戻り値の型だけを変えたいときは、レストパラメータと Parameters ユーティリティ型を使えばよい。ただし、この書き方は関数型を適用するより面倒である。個々の引数の型を書き出すのとどちらがよいかは、状況に応じて判断する。
async function fetchANumber(
...args: Parameters<typeof fetch>
): Promise<number> {
...
}関数型とコールバック
Array の map や filter のようにコールバックを受け取る関数を使うと、TypeScript はコールバックの引数の型を推論する。そして、推論した型をコールバックとして渡した関数式に適用する。