← ホームに戻る

TypeScript基礎 - インターフェースとジェネリクス

再利用可能な型定義の方法を学ぼう

インターフェースとジェネリクス

より複雑で再利用可能な型定義を学びましょう。


インターフェース (Interface)

インターフェースは、オブジェクトの「形」を定義する機能です。同じ形のオブジェクトを何度も使う場合に便利です。

基本的な使い方

// インターフェースの定義 interface User { name: string; age: number; email: string; } // インターフェースを使う const user1: User = { name: "太郎", age: 25, email: "taro@example.com" }; const user2: User = { name: "花子", age: 23, email: "hanako@example.com" };

メリット:

  • 型定義を再利用できる
  • コードが読みやすくなる
  • 同じ形のオブジェクトを複数作る時に便利

オプショナルプロパティ

必須ではないプロパティには ? をつけます。

interface User { name: string; age: number; email: string; phone?: string; // phoneは省略可能 } // phoneがなくてもOK const user1: User = { name: "太郎", age: 25, email: "taro@example.com" }; // phoneがあってもOK const user2: User = { name: "花子", age: 23, email: "hanako@example.com", phone: "090-1234-5678" };

読み取り専用プロパティ

変更してほしくないプロパティには readonly をつけます。

interface User { readonly id: number; // 読み取り専用 name: string; age: number; } const user: User = { id: 1, name: "太郎", age: 25 }; // user.id = 2; // エラー!idは読み取り専用なので変更できない user.name = "次郎"; // OK

ジェネリクス (Generics)

ジェネリクスは、「型をパラメータとして受け取る」機能です。柔軟で再利用可能なコードを書けます。

なぜジェネリクスが必要?

例えば、配列の最初の要素を返す関数を考えてみましょう。

❌ ジェネリクスを使わない場合

// 数値配列用 function firstNumber(arr: number[]): number { return arr[0]; } // 文字列配列用 function firstString(arr: string[]): string { return arr[0]; } // 型ごとに関数を作る必要がある... 😰

✅ ジェネリクスを使う場合

function first<T>(arr: T[]): T { return arr[0]; } // どんな型でも使える! const num = first([1, 2, 3]); // numはnumber型 const str = first(["a", "b", "c"]); // strはstring型

ジェネリクスの書き方

<T> の部分が「型パラメータ」です。Tは慣習的によく使われますが、任意の名前でOKです。

// 基本形 function 関数名<T>(引数: T): T { return 引数; }

実用的な例:データのラッパー

interface ApiResponse<T> { data: T; status: number; message: string; } // ユーザーデータのレスポンス const userResponse: ApiResponse<User> = { data: { name: "太郎", age: 25, email: "taro@example.com" }, status: 200, message: "Success" }; // 商品データのレスポンス interface Product { id: number; name: string; price: number; } const productResponse: ApiResponse<Product> = { data: { id: 1, name: "ノートPC", price: 120000 }, status: 200, message: "Success" };

複数の型パラメータ

function pair<T, U>(first: T, second: U): [T, U] { return [first, second]; } const result1 = pair("age", 25); // [string, number] const result2 = pair(true, "success"); // [boolean, string]

インターフェース vs 型エイリアス

TypeScriptには、インターフェース以外に「型エイリアス」という機能もあります。

// インターフェース interface User { name: string; age: number; } // 型エイリアス type User = { name: string; age: number; };

どちらを使うべき?

  • オブジェクトの型定義:インターフェースを推奨
  • ユニオン型やプリミティブ型:型エイリアスを使う
// こういう場合は型エイリアスを使う type Status = "pending" | "success" | "error"; type ID = string | number;

実践例:Todoアプリの型定義

interface Todo { id: number; title: string; completed: boolean; createdAt: Date; tags?: string[]; } interface TodoList<T> { items: T[]; add: (item: T) => void; remove: (id: number) => void; } // 使用例 const myTodos: TodoList<Todo> = { items: [ { id: 1, title: "TypeScriptを学ぶ", completed: false, createdAt: new Date(), tags: ["学習", "プログラミング"] } ], add: (todo) => { myTodos.items.push(todo); }, remove: (id) => { myTodos.items = myTodos.items.filter(item => item.id !== id); } };

まとめ

インターフェース

  • オブジェクトの「形」を定義する
  • ? でオプショナルプロパティ
  • readonly で読み取り専用プロパティ
  • 再利用可能で読みやすいコードを書ける

ジェネリクス

  • 型をパラメータとして受け取る
  • <T> のように書く
  • 柔軟で再利用可能な関数やインターフェースを作れる
  • 型安全性を保ちながら汎用的なコードが書ける

次はReactの基礎を学びましょう!