概要
関数に対するTypeScriptの作法について、学んだため共有する。自身の勉強も兼ねてTypeScriptを用いて関数を作成する際どうしたらいいのかがわからない人を対象に作成した。
作成関数に対する型アノテーションの設定
TypeScriptでは、基本的に関数の**「パラメーター」と「戻り値」**に型アノテーションを設定することができる。しかし、できるだけTypeScriptに型を推論をさせ、明示的な型アノテーションせず、コード量を減らすことが、TypeScriptのコード作成では良いとされている。パラメーターに関しては推論できないため、型アノテーションは必須である。戻り値に関しては推論することが可能なので、省略することが普通である。
// パラメーター、戻り値に対して型アノテーションを設定
function add(a: number, b: number): number {
return a + b;
}
// 戻り値の型アノテーションを省略
function add(a: number, b: number) {
return a + b;
}
呼び出す際は、型定義をする必要はない。
add(1, 3); // 戻り値は4
オプションパラメーター
パラメータを省略可能とする際は、パラメータの語尾に?
をつける。必須パラメーターを先に指定し、省略可能パラメーターは後に記述する必要がある。
function log(message: string, id?: string) {
console.log(message, id || 'Not id');
}
log('hoge'); // hoge Not id
log('hoge', '12345'); // hoge 12345
デフォルトパラメーター
オプションパラメーターにデフォルト値を与えることができる。これをデフォルトパラメーターと呼ぶ。オプションパラメーターと同様に引数を省略することができる。デフォルトパラメーターは、パラメーターのリストの最後にする必要はない。通常は、オプションパラメーターを使用するよりデフォルトパラメーターを使用するとよい。
function log(message: string, id='Not id') {
console.log(message, id);
}
log('hoge'); // hoge Not id
log('hoge', '12345'); // hoge 12345
レストパラメーター
引数を指定する際、固定数ではなく可変長となる関数もあるだろう。その際は、レストパラメーターを使用する。パラメーターの前に...
をつけるだけである。一つの関数にレストパラメーターは一つまでである。また、パラメーターのリストの最後に記述する必要がある。
function sum(...numbers: number[]) {
return numbers.reduce((total, n) => total + n, 0);
}
sum(1, 2, 3); // 6
sum(1, 3); // 4
呼び出しシグネチャ
パラメーターと戻り値のそれぞれの型を定義してきたが、関数としての型も存在する。それを呼び出しシグネチャと呼ぶ。関数は引数と戻り値を所有しているためそれを用いてい関数の型を定義する。
// 呼び出しシグネチャ
(a: number, b: number) => number // 引数の型 => 戻り値の型
デフォルトパラメーターで使用した例を呼び出しシグネチャを用いて書き変える。呼び出しシグネチャで型がアノテーションされているので、パラメーターのところで型アノテーションを指定する必要がない。
type Log = {message: string, id?: string) => void
const log: Log = (message, id='Not id') => {
console.log(message, id);
}
log('hoge'); // hoge Not id
log('hoge', '12345'); // hoge 12345
コールバック関数
コールバック関数を呼び出す際も、呼び出しシグネチャを使用する。
function times(f: (index: number) => void, n: number) {
for(let i = 0; i < n; i++) {
f(i);
}
}
times(n => console.log(n), 4); // 0 1 2 3
オーバーロードされた関数
呼び出しシグネチャの記法は、もう一つある。たいていは、省略記法を用いるとよいが、完全版の記述が適する場合がある。それが、オーバーロードされた関数の時である。オーバーロード関数は、複数の呼び出しシグネチャを持つ関数のことである。
// 省略的な書き方
type Add = (a: number, b: number) => number
// 完全な書き方
type Add {
(a: number, b: number): number
}
ここで、一日だけの予定と数日に渡る予定を決めることができるオーバーロード関数schedule
を考える。2つの呼び出しシグネチャを想定して、関数scheduleを設計する必要がある。
type Schedule = {
(from: Date, to: Date, place: string): Scheduled
(from: Date, place: string): Scheduled
}
const schedule: Schedule = (from: Date, toOrPlace: Date | string, place?: string) => {
if(toOrPlace instanceof Date && place !== undefined) {
// 数日の予定
} else if(typeof toOrPlace === 'string') {
// 1日だけの予定
}
}
schedule(date1, date2, 'ホテル'); // 数日の予定
schedule(date, '図書館'); // 1日だけの予定
終わりに
以上、TypeScriptの関数宣言と呼び出しについてまとめた。間違っている個所等あればコメントお願いします。