😺

TypeScriptのtypeとinterfaceの違いを解説

に公開

基本的な違い

interface(インターフェース)

  • オブジェクトの形状を定義するのに特化
  • 同じ名前で再宣言すると自動的にマージされる
  • extendsで継承可能

type(型エイリアス)

  • あらゆる型を定義できる(オブジェクト、ユニオン型、プリミティブ型など)
  • 再宣言できない
  • &(交差型)で拡張可能

具体例で比較

1. 基本的な使い方

// ✅ どちらも同じように使える
interface UserInterface {
  id: number
  name: string
}

type UserType = {
  id: number
  name: string
}

2. 拡張・継承

// interface - extendsで継承
interface Animal {
  name: string
}
interface Dog extends Animal {
  breed: string
}

// type - 交差型(&)で拡張
type Animal = {
  name: string
}
type Dog = Animal & {
  breed: string
}

3. typeだけができること

// ✅ ユニオン型
type Status = 'pending' | 'completed' | 'failed'

// ✅ プリミティブ型のエイリアス
type UserId = string

// ✅ タプル型
type Coordinate = [number, number]

// ❌ interfaceではできない
interface Status = 'pending' | 'completed' // エラー!

4. interfaceだけができること

// ✅ 同名で宣言するとマージされる
interface User {
  name: string
}
interface User {
  age: number
}
// 結果: User は { name: string; age: number } になる

// ❌ typeは再宣言できない
type User = { name: string }
type User = { age: number } // エラー!

使い分けの指針

interfaceを使う場面

// ✅ Reactコンポーネントのprops
interface ButtonProps {
  label: string
  onClick: () => void
}

// ✅ クラスの実装
interface Flyable {
  fly(): void
}
class Bird implements Flyable {
  fly() { /* ... */ }
}

typeを使う場面

// ✅ ユニオン型
type Theme = 'light' | 'dark'

// ✅ 関数の型
type ClickHandler = (event: MouseEvent) => void

// ✅ 複雑な型の組み合わせ
type ApiResponse<T> = {
  data: T
  status: 'success' | 'error'
}

自分のコードの場合

// ✅ props定義なのでinterface(推奨)
interface BulkListProps {
  ownerId: number
}

// 🤔 オブジェクトの形状だけなので、interfaceでも良い
interface Bulk {
  id: number
  createdAt: string
  totalUrls: number
}

まとめ

  • オブジェクトの形状だけなら → interface
  • ユニオン型や複雑な型なら → type
  • Reactのpropsなら → interface(慣習的に)
  • 迷ったら → チームの規約に従う、なければtypeで統一

Discussion