ジェネリック関数
型引数を宣言する
関数名の後ろに山カッコで名前を書くと、その関数の中だけで使える型の箱ができます。これを型引数と呼びます。
function first<T>(items: T[]): T {
return items[0];
}T が箱です。引数を T[]、戻り値を T と書いたので、受け取った配列の要素と返す値は同じ型だ、という関係だけを宣言したことになります。その型が何なのかは、まだ決めていません。
中身は呼び出した瞬間に決まる
決めるのは呼ぶ側です。渡した配列から TypeScript が推論します。
const titles = ["プロフィールサイト", "自己紹介カード"];
const ids = [1, 2, 3];
const a = first(titles); // a は string
const b = first(ids); // b は numberany 版と違い、返ってきた値の型が残っています。
a.toFixed(2);
// エラー Property 'toFixed' does not exist on type 'string'.関数は 1 本のまま、検査は型ごとに効いています。これがジェネリクスの取り分です。
名前は T でなくてもよい
T は type の頭文字で、慣習としていちばんよく使われるだけです。読み手に伝わる名前も付けられます。
function first<Item>(items: Item[]): Item {
return items[0];
}呼ぶ側から指定することもできる
推論に任せず、中身を書いて渡すこともできます。
const c = first<string>(titles);ふだんは書きません。推論がうまく効かないときの逃げ道として、こういう書き方があることだけ覚えておいてください。
手を動かす
演習では、配列の先頭を返す first を書きます。いまは引数の型が無いので動きません。どんな配列を渡しても、その要素の型がそのまま戻り値の型になるように、型引数を使って書いてください。
要件
- 型引数を 1 つ宣言する
- 引数は宣言した型引数の配列にする
- 戻り値は宣言した型引数そのものにする
anyは使わない
入出力例
first(["プロフィールサイト","自己紹介カード","スキル一覧の表"]) → "プロフィールサイト"
first([7,3,1]) → 7
first([true,false,true]) → true
first([{"id":1,"title":"プロフィールサイト"},{"id":2,"title":"自己紹介カード"}]) → {"id":1,"title":"プロフィールサイト"}
first(["スキル一覧の表"]) → "スキル一覧の表"ヒント
編集 LuaGate編集部