interface<T> ジェネリックインターフェース
最終更新:2026-10-22
interface<T> ジェネリックインターフェース
ジェネリックインターフェースは名前の後に型パラメータを付け(interface ApiResult<T>)、「容器の形状」と「中身」を切り離します。ApiResult<UserBrief> と ApiResult<number[]> は同じ構造で、中身の型が違うだけです。インターフェース、API レスポンス、ストレージ構造がこれで再利用されます。
| グループ | ジェネリクス |
|---|---|
| 種類 | 構文 |
| strict モード | 不要 |
ℹ️ 説明 エディタは TypeScript を JavaScript にトランスパイルして実行します(型チェックなし)。型チェック結果は各サンプルの出力を参照してください。
📝 構文
interface ApiResult<T> {
code: number;
data: T;
}
// 複数の型パラメータ + デフォルト値もサポート
interface Paginated<T, Page = number> {
page: Page;
items: T[];
}
⚙️ パラメータ
| <T> | 型パラメータ:使用時に具体型を埋めます(ApiResult<UserBrief>)。文脈から推論される場合もあります |
|---|---|
| data: T | 中身のフィールドは T と連動します。res1.data は自動的に UserBrief であり、読み書きの両方が検査されます |
戻り値:ジェネリックインターフェースは型レベルの概念で、実行時コードを生成しません。インスタンス化された型がフィールドの読み書きの型を決めます。
▶ サンプル
下のコードを編集して「試す」を押すと、トランスパイル実行結果を確認できます:
出力:
Ada admin 20
(トランスパイル後の実行出力。res1.data に数値を入れたり、res2.data.name にアクセスしたりするとコンパイルエラーになります——T はすでに確定しています)
💡 ポイント
ℹ️ 説明 ジェネリックインターフェースを使うときは型パラメータを必ず指定する必要があります(デフォルト値を持つ場合を除く)。ApiResult 単体は「未インスタンス化」の状態で、変数型としてそのまま使うとエラーになります。
💡 ヒント ネストの局面では直接組み合わせます。ApiResult<Paginated<Order>> のように1層ずつ包むほうが、code/data/page/items を手書きで平らに並べるより明快です。
⚠️ 注意 やみくもにジェネリックにしないこと。インターフェースが1回しか使われず型も固定なら、具体型を直接書くほうが直感的です。ジェネリックの価値は、同じ形状を複数の中身に再利用することにあります。
🏷️ 関連ジェネリクス
💡 関連ケース
ケースは今後追加予定です。
📚 関連チュートリアル
❓ よくある質問
Q ジェネリックインターフェースとジェネリックな type エイリアスはどう使い分けますか?
A 表現力はほぼ同等です。宣言マージ、extends による継承、クラスの implements が必要なら interface。ユニオン、マップ、条件の組み合わせが必要なら type です。
Q インターフェースのメソッド上のジェネリックと、インターフェース自体のジェネリックの違いは何ですか?
A interface Box<T> { open(): T } の T はインターフェース全体で共用です(同じ Box<string> インスタンスではすべての T が同じ)。interface Maker { make<T>(): T } の T は呼び出しごとに個別に決まります。前者は「容器」、後者は「動作」です。
Q ジェネリックインターフェースは型パラメータを制約できますか?
A できます。構文は関数と同じです。interface KeyedStore<T extends { id: string }> { get(id: string): T | undefined } ——制約を満たさない型は使用箇所で直接エラーになります。