T extends U ジェネリック制約

最終更新:2026-10-22

T extends U ジェネリック制約

制約(extends)は型パラメータに「範囲を定め」ます。<T extends HasId> は「T は少なくとも id: number を持つ」と約束します。制約の内側では T の公開メンバーに安心してアクセスでき、制約の外側(string を渡すなど)はコンパイル時に拒否されます。any より安全で、具体型より柔軟です。

グループジェネリクス
種類構文
strict モード不要

ℹ️ 説明 エディタは TypeScript を JavaScript にトランスパイルして実行します(型チェックなし)。型チェック結果は各サンプルの出力を参照してください。

📝 構文

interface HasId {
  id: number;
}

function findById<T extends HasId>(items: T[], id: number): T | undefined {
  return items.find((item) => item.id === id);
}

⚙️ パラメータ

T extends HasId制約:実引数の型は HasId と互換(少なくとも id: number を含む)でなければなりません
T | undefined戻り値型は実引数の正確な形状を保持します。どんな形状の配列を渡せば、同じ形状の要素を取り返します

戻り値:制約なしのジェネリックと同じです——実引数の正確な型は保持されます。違いは、関数本体の中で T の使えるメンバーが増える点です。

▶ サンプル

下のコードを編集して「試す」を押すと、トランスパイル実行結果を確認できます:

出力:

Desk
見つかりません

(トランスパイル後の実行出力。products の要素に余分なフィールドがあっても構いません——構造的型付けは制約が要求するメンバーだけを検査します)

💡 ポイント

ℹ️ 説明 制約は「完全一致」を求めません。{ id: 1, name: "Lamp", price: 59 } の余分なフィールドは互換性に影響しません。構造的型付けは制約が要求するメンバーが揃っているかだけを見ます。
💡 ヒント インラインの制約は中間インターフェースを省きます。function sumLengths<T extends { length: number }>(a: T, b: T) は「length があればよい」と直接記述できます。複雑になったときだけインターフェースに切り出します。
⚠️ 注意 制約が与えるのは「下限」です。T extends HasId は id の存在しか保証せず、item.name はコンパイラの目にはまだ存在しません——name: string も追加で制約しない限り。
ケースは今後追加予定です。

📚 関連チュートリアル

❓ よくある質問

Q 制約とジェネリックのデフォルト値は同時に使えますか?
A 使えますし、よく組み合わせます:<T extends HasId = User> ——未指定ならデフォルトの User、指定する場合は HasId を満たす必要があります。デフォルト値は制約の範囲内でなければなりません。
Q 「いくつかのリテラルのいずれか」に制約するには?
A リテラルのユニオンを使います。function set<K extends "light" | "dark">(theme: K)。K は具体的なリテラルに絞り込まれ、範囲外の値はコンパイルエラーになります。
Q 複数の型パラメータが互いに制約し合うには?
A 後のパラメータに前のパラメータを参照させます。<K extends keyof T> ——K の取りうる範囲が T で決まります。これが keyof パターンの核心で、キー名がオブジェクトと実際に一致することを保証します。
Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%