Kodokon kodokon.com

ジェネリクス: シンプルなジェネリック関数と型

呼び出しのたびに完全な型の精度を保つ、再利用可能な関数と型を書きましょう。

9 分 · 3 問

このレッスンを Kodokon で開く

あなたはすでに、気づかないうちにジェネリクスを使っています。string[]Promise<number>……。自分で書いてみるときが来ました。ジェネリクスは型パラメータを導入します。これは使うたびに具体的な型に置き換えられる変数です。目的は、型の精度を犠牲にせず、ロジックを一度だけ書くことです。

TYPESCRIPT
function first<T>(items: T[]): T | undefined {
  return items[0];
}

const n = first([10, 20, 30]);
const s = first(["a", "b"]);
T は推論される: n は number | undefined、s は string | undefined

呼び出し側では何も指定しなかったことに注目してください。TypeScript は引数から T推論します。制約のないジェネリクスは何でも受け入れますが、関数はしばしばデータについて最低限の保証を必要とします。extends キーワードは T に最小限の形を課します。

TYPESCRIPT
interface HasId {
  id: number;
}

function findById<T extends HasId>(
  items: T[],
  id: number
): T | undefined {
  return items.find((item) => item.id === id);
}
制約: T は少なくとも数値の id を持たなければならない

型自身もジェネリックにできます。これはネットワークコードの日常です。レスポンスの構造は安定していて、変わるのは data の中身だけ。すると1つの型が、あなたのすべての API レスポンスを記述します。

TYPESCRIPT
interface ApiResponse<T> {
  ok: boolean;
  data: T;
}

type UserResponse = ApiResponse<{ name: string }>;

const res: UserResponse = {
  ok: true,
  data: { name: "Ada" },
};
ジェネリック型が data の中身をパラメータ化する

理解度チェック

このレッスンの要点をしっかり覚えているか確認しましょう。

  1. function first<T>(items: T[]): T | undefined において、T は何を表しますか?
    • 一度きり定義される具体的な型
    • 呼び出しのたびに置き換えられる型パラメータ
    • unknown 型
    • any の省略形
  2. 制約 <T extends HasId> は何を保証しますか?
    • T はちょうど HasId 型である
    • T は少なくとも HasId のプロパティを持つ
    • T は HasId クラスを継承する
  3. 型を指定せずに first([10, 20, 30]) を呼び出します。T は何になりますか?
    • any
    • unknown
    • number
    • 10 | 20 | 30