📚

【TypeScript】typeとinterfaceの機能比較表つくってみた

2025/01/03に公開

typeとinterfaceの機能比較表

機能 type interface
オブジェクト型の定義
継承
宣言のマージ
ユニオン型
インターセクション型
プリミティブ型のエイリアス
タプル型の定義
関数型の定義
計算プロパティ
マップ型の定義

オブジェクト型の定義

typeinterfaceも可能

type.ts
// UserTypeを定義
type UserType = {
    id: number;
    name: string;
    email: string;
};

const user: UserType = {
    id: 1,
    name: "John Doe",
    email: "john.doe@example.com"
};
interface.ts
// UserInterfaceを定義
interface UserInterface {
    id: number;
    name: string;
    email: string;
}

const user: UserInterface = {
    id: 1,
    name: "John Doe",
    email: "john.doe@example.com"
};

継承

typeinterfaceも可能

type.ts
// 基本のUserTypeを定義
type UserType = {
    id: number;
    name: string;
};

// 管理者用のAdminTypeを定義し、UserTypeを継承
type AdminType = UserType & {
    role: string;
};

const admin: AdminType = {
    id: 1,
    name: "Alice",
    role: "Administrator"
};
interface.ts
// 基本のUserInterfaceを定義
interface UserInterface {
    id: number;
    name: string;
}

// 管理者用のAdminInterfaceを定義し、UserInterfaceを継承
interface AdminInterface extends UserInterface {
    role: string;
}

const admin: AdminInterface = {
    id: 1,
    name: "Alice",
    role: "Administrator"
};

宣言のマージ

  • interfaceのみ可能
  • 宣言のマージとは
    • 同じ名前のinterfaceを複数回宣言でき、自動的に1つにマージされる
interface.ts
// 最初のインターフェース宣言
interface User {
    id: number;
    name: string;
}

// 二つ目のインターフェース宣言
interface User {
    email: string;
}

// 三つ目のインターフェース宣言
interface User {
    age: number;
}

// マージされたインターフェースを使用
const user: User = {
    id: 1,
    name: "John Doe",
    email: "john.doe@example.com",
    age: 30
};

ユニオン型(|)

  • typeのみ可能
  • 複数の型のいずれかをとる型をユニオン型という
type.ts
type ID = number | string;

let userId: ID;

userId = 123; // OK
userId = "abc"; // OK
userId = true; // エラー: 'boolean' 型は 'number' | 'string' 型に割り当てることができません

インターセクション型(&)

  • typeのみ可能
  • 複数の型を組み合わせて両方の型をもつ型をインターセクション型という
type.ts
type Person = {
    name: string;
    age: number;
};

type Employee = {
    employeeId: number;
};

type EmployeePerson = Person & Employee;

const employee: EmployeePerson = {
    name: "John Doe",
    age: 30,
    employeeId: 12345
};

プリミティブ型のエイリアス

  • typeのみ可能
  • プリミティブ型のエイリアスとは
    • プリミティブ型とは基本的なデータ型のこと
      • string,number,booleanなど
    • エイリアスとは
      • 別名をつけること
type.ts
type MyString = string;
type MyNumber = number;
type MyBoolean = boolean;

let greeting: MyString = "Hello, world!";
let age: MyNumber = 30;
let isStudent: MyBoolean = true;

タプル型の定義

  • typeのみ可能
  • タプル型とは
    • 配列の要素数と各要素の型を固定できる
type.ts
// タプル型を定義
let person: [string, number];

// 値を割り当て
person = ["Alice", 30]; // OK

// 型に合わない値を割り当てるとエラー
person = [30, "Alice"]; // エラー: 'number' 型は 'string' 型に割り当てることができません

関数型の定義

typeinterfaceも可能

type.ts
// 関数型を定義
type Greet = (name: string) => string;

// 関数の実装
const greet: Greet = (name: string) => {
    return `Hello, ${name}!`;
};
console.log(greet("Alice")); // 出力: "Hello, Alice!"
interface.ts
interface Calculator {
    (a: number, b: number): number;
}

// 使用例
const add: Calculator = (a, b) => a + b;

計算プロパティ

  • typeのみ可能
  • 計算プロパティとは
    • オブジェクトのプロパティ名を動的に生成できる機能のこと

下記の例では、

  • [K in ...] という構文を使用
  • '月' | '火' | '水'の各値に対して
  • boolean 型のプロパティを生成
type.ts
// 曜日の例
type Days = {
    [K in '月' | '火' | '水']: boolean;
}

マップ型の定義

  • typeのみ可能
  • マップ型とは
    • オブジェクトのキーと値の型パターンを定義できる
type.ts
type StringMap = {
    [key: string]: string;
}

const userNames: StringMap = {
    "001": "田中",
    "002": "山田",
    "003": "佐藤"
};

typeとinterfaceの使い分けの基準

  • typeを使うとき
    • ユニオン型、インターセクション型、タプル型の定義
    • プリミティブ型のエイリアス
  • interfaceを使うとき
    • オブジェクトの構造を定義
    • 継承や拡張が必要なとき

個人的な考え

typeを使うときは、あくまで「自由に使えるデータ型」を宣言するイメージで、interfaceはオブジェクト指向的な考えで、typeをつかってあるオブジェクトを定義するときに使うイメージ

Discussion