[TypeScript学習記録]  typeとInterfaceとは

TypeScriptにおける **`type`**（型エイリアス）と **`interface`** は、どちらも型を定義するための構文で、オブジェクトやデータの構造を記述する際に使用される。

## 1. `type`とは
`type`は、**型エイリアス**（型の別名）を作成する構文で、特定の型や値の構造に名前を付けて再利用可能にできる。オブジェクト型だけでなく、プリミティブ型、ユニオン型、交差型、リテラル型など、幅広い型を定義可能。

### 特徴
- **単一定義**：同じ名前での再定義は不可（上書きできない）。
- **演算子を使用**：`|`（ユニオン）や`&`（交差）で型を組み合わせ可能。
- **ジェネリクス対応**：型パラメータをサポート。

### サンプルコード
```typescript
// オブジェクト型の定義
type User = {
  id: number;
  name: string;
  email?: string;
};

const user: User = { id: 1, name: "Alice" };

// ユニオン型の定義
type ID = number | string;
let userId: ID = "abc123";

// 交差型の定義
type Point = { x: number } & { y: number };
const point: Point = { x: 10, y: 20 };

// リテラル型の定義
type Status = "success" | "error";
let status: Status = "success";
```

### ユースケース
- プリミティブ型やユニオン型を定義（例：`type Role = "admin" | "user"`）。
- 複雑な型操作（例：交差型やジェネリクス）。
- 一時的な型や単発の型定義。

---

## 2. `interface`とは
`interface`は、オブジェクトやクラスの構造を定義するための構文で、主に**オブジェクトの形状**や**クラスの契約**を記述。TypeScriptの構造的型システムに基づき、特定のプロパティやメソッドを持つ型を保証。

### 特徴
- **オブジェクト/クラス特化**：主にオブジェクト型やクラスの型定義に使用。
- **マージ可能**：同じ名前の`interface`を複数定義すると、自動的にマージされる。
- **継承対応**：`extends`で他のインターフェースを拡張可能。
- **実装対応**：`implements`キーワードを使用して、インターフェースを実装。

### サンプルコード
```typescript
// 基本的なインターフェース
interface User {
  id: number;
  name: string;
  email?: string;
}

const user: User = { id: 1, name: "Alice" };

// インターフェースのマージ
interface User {
  role: string;
}

const admin: User = { id: 2, name: "Bob", role: "admin" }; // emailもroleも含む

// インターフェースの拡張
interface Admin extends User {
  permissions: string[];
}

const superAdmin: Admin = {
  id: 3,
  name: "Charlie",
  role: "superadmin",
  permissions: ["read", "write"],
};

// クラスの実装
interface Printable {
  print(): void;
}

class Document implements Printable {
  print() {
    console.log("Printing...");
  }
}
```

### ユースケース
- オブジェクトやクラスの構造を定義（例：APIレスポンス、コンポーネントのprops）。
- 複数のモジュールでインターフェースを拡張（マージ）。
- クラスやライブラリの型定義。

---

## 3. `type`と`interface`の主な違い
| 比較項目    | `type`      | `interface`              |
| ------- | ----------- | ------------------------ |
| 再定義     | ❌ 不可        | ⚪ マージされる                 |
| ユニオン型   | ⚪ 対応        | ❌ 非対応（オブジェクトに限られる）       |
| 交差型（合成） | ⚪ &演算子で可能 | ⚪ extends キーワードで可能     |
| プリミティブ型 | ⚪ 定義可能      | ❌ 定義不可                   |
| クラス実装 | ⚪ 可能 (implements不可)   | ⚪ implements で明示的に連携可能 |
| マージ挙動   | ❌ 上書きエラー    | ⚪ 自動的に統合                 |

### マージの例
```typescript
// interface: マージされる
interface User {
  name: string;
}
interface User {
  age: number;
}
const user: User = { name: "Alice", age: 25 }; // OK

// type: マージ不可
type Point = { x: number };
// type Point = { y: number }; // エラー: 再定義不可
```

### 拡張の例
```typescript
// interface: extendsで拡張
interface Person {
  name: string;
}
interface Employee extends Person {
  job: string;
}

// type: 交差型で拡張
type PersonType = { name: string };
type EmployeeType = PersonType & { job: string };
```

## 4. 使い分け

### `type`を選ぶ場合
- **プリミティブ型やユニオン型を定義**：
  ```typescript
  type Role = "admin" | "user";
  type ID = number | string;
  ```
- **複雑な型操作**（ジェネリクス、交差型、ユーティリティ型など）：
  ```typescript
  type PartialUser = Partial<{ id: number; name: string }>;
  ```
- **一時的または単発の型**：再利用や拡張が不要な場合。
- **柔軟性が欲しい**：型エイリアスは幅広い型に対応。

### `interface`を選ぶ場合
- **オブジェクト型やクラスの構造を定義**：
  ```typescript
  interface User {
    id: number;
    name: string;
  }
  ```
- **マージが必要**：ライブラリやモジュール間で型を拡張。
  ```typescript
  interface Window {
    customProperty: string; // グローバル型を拡張
  }
  ```
- **クラス実装**：クラスが特定のインターフェースを満たす必要がある場合。
  ```typescript
  interface Printable {
    print(): void;
  }
  class Document implements Printable {
    print() {}
  }
  ```

### 注意点
意図しない型の競合に注意
複数のライブラリやスクリプトが同じインターフェース名を使っていると、型の競合が起きる。

```typescript
// 意図しない競合例
interface Window {
  customProp: string;
}
interface Window {
  customProp: number; // ❌ 型の衝突が発生（エラー）
}
```
→ このような場合、衝突を避けるために type の使用やスコープ分離が推奨される。



## まとめ
- **`type`**：柔軟で、ユニオン型やプリミティブ型、複雑な型操作に最適。単一定義で再定義不可。
- **`interface`**：オブジェクト型やクラスに特化。マージや継承が強力。
- **使い分け**：オブジェクト型や拡張性なら`interface`、ユニオン型や一時的な型なら`type`。