ジェネリック関数

型引数を宣言する

関数名の後ろに山カッコで名前を書くと、その関数の中だけで使える型の箱ができます。これを型引数と呼びます。

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 は number

any 版と違い、返ってきた値の型が残っています。

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. 型引数を 1 つ宣言する
  2. 引数は宣言した型引数の配列にする
  3. 戻り値は宣言した型引数そのものにする
  4. any は使わない

入出力例

first(["プロフィールサイト","自己紹介カード","スキル一覧の表"])"プロフィールサイト" first([7,3,1])7 first([true,false,true])true first([{"id":1,"title":"プロフィールサイト"},{"id":2,"title":"自己紹介カード"}]){"id":1,"title":"プロフィールサイト"} first(["スキル一覧の表"])"スキル一覧の表"

ヒント

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部
main.ts
main.ts
学習モード

メモ

ジェネリック関数

⌘S で保存