2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【TypeScript初心者】ユニオン型、インターセクション型を理解する

Last updated at Posted at 2025-12-11

はじめに

「読んで学ぶTypeScript」をちょっとずつ読み進めます!
今回は、ユニオン型、インターセクションについてです!


コーディングに慣れていないので、ところどころ用語を調べて記載しながら書きますmm
そのため、初心者の方が理解するには、助けになるかもしれません :crab:


既存の型だけでは不便なことがある

TypeScriptには、stringnumberなどのプリミティブ型以外に、それらを組み合わせてより複雑なデータを表現する機能があるらしいです。

今回はユニオン型・インターセクション型ついて学びます :pencil:

ユニオン型とは

  • ユニオン型(union type)は「いずれかの型」を持つ
    • 「OR」の考え方
  • 2つ以上の型を|で繋げて書く
    • 例:number型もしくはundefined型 = number | undefined
  • 配列にユニオン型を使う時は、()で囲う
// 配列にユニオン型を使いたい時のNG例
type List = string | number[]; 
// 「単一の文字列 (string)」または「数値のみの配列 (number[])」という意味になる

let listC: List = ["Hello", 10, 20]; 
// これは「文字列と数値が混ざった配列」なので、上記のどちらの型にも合致せず、エラーになる
// 配列にユニオン型を使いたい時のOK例
type List = (string | number)[];
// 配列の要素の型が、文字列か数値のどちらかであるという意味になる

let listC: List = ["Hello", 10, 20]; 
// 文字列と数値を混ぜてもOK(文字列だけの配列でも、数値だけの配列でもOK)

判別可能なユニオン型

  • 通常のユニオン型だと、中身の型がごちゃ混ぜになっていて、判断するために複雑な分岐が必要になる
  • 判別可能なユニオン型は、各オブジェクトの型を判別するためのプロパティ(しるし)を持っている
    • このプロパティを ディスクリミネータ(discriminator) と呼ぶ

判別可能なユニオン型が便利な例

// UploadStatus - ファイルアップロードの状況を表現したユニオン型
type UploadStatus = InProgress | Success | Failure;
type InProgress = { done: boolean; progress: number };
type Success = { done: boolean };
type Failure = { done: boolean; error: Error };
意味 done progress error
InProgress アップロード中 false 進捗率(%) -
Success アップロード成功 true - -
Failure アップロード失敗 true - エラー詳細

上記の状態を判断して表示させる関数の実装の場合、判別可能になっていないユニオン型だと、

function printStatus(status: UploadStatus) {
  if (status.done === false) {
    console.log(`アップロード中:${status.progress}%`); 
    // エラーになる(progressプロパティが、type Success,Failureにはない)
  }
}
  • status.done === false で、InProgressに絞っているはず
  • しかし、コンパイラーは if分岐内で、statusがSuccessやFailureかもしれないと考えるため、エラーになる
  • 解消するには、progressがあることをチェックする必要がある↓
function printStatus(status: UploadStatus) {
  if (status.done === false && "progress" in status) {
    //                         ^^^^^^^^^^^^^^^^^^^^追加
    console.log(`アップロード中:${status.progress}%`);
    // コンパイルエラーが解消!
  }
}
  • このチェックを全ての状態で挟むと、コードが冗長になる...
  • そこで、ディスクリミネータ(type)を追加して、InProgress,Success,Failureのどの状態か判別できるようにする
意味 ディスクリミネータ progress error
InProgress アップロード中 type: "InProgress" 進捗率(%) -
Success アップロード成功 type: "Success" - -
Failure アップロード失敗 type: "Failure" - エラー詳細
function printStatus(status: UploadStatus) {
  if (status.type === "InProgress") {
    console.log(`アップロード中:${status.progress}%`);
  } else if (status.type === "Success") {
    console.log("アップロード成功", status);
  } else if (status.type === "Failure") {
    console.log(`アップロード失敗:${status.error.message}`);
  } else {
    console.log("不正なステータス: ", status);
  }
}

ディスクリミネータを追加すると、分岐処理が読みやすく、保守性も高くなる!

インターセクション型とは

  • インターセクション型(intersection type)は一つの値が複数の型を持つことができる
    • 「AND」の考え方
  • 既存の型を結合して、新たな型を作る際に便利
  • 合成したいオブジェクト同士を&で列挙して書く
// 例
type Name = {
  name: string
}

type Age = {
  age: number
}

type Person = Name & Age
// ^^^インターセクション型

const person: Person = {
  name: 'John',
  age: 20,
}

インターセクション型が便利な例

// パラメーターがめちゃくちゃ増えた...
type Parameter = {
  id: string;
  index?: number;
  active: boolean;
  balance: number;
  photo?: string;
  age?: number;
  surname: string;
  givenName: string;
  company?: string;
  email: string;
  phoneNumber?: string;
  address?: string;
  // ...
};
  • 必須のものとそうでないものが分かりづらい
  • 必須とそうでないパラメータのタイプエイリアスに分離して、インターセクション型で合成する
// Required<T>: 全プロパティを必須にする
type Mandatory = Required<{
  id: string;
  active: boolean;
  balance: number;
  surname: string;
  givenName: string;
  email: string;
}>;

 // Partial<T>: 全プロパティをオプショナルにする
type Optional = Partial<{
  index: number;
  photo: string;
  age: number;
  company: string;
  phoneNumber: string;
  address: string;
}>;

// インターセクション型で合体
type Parameter = Mandatory & Optional;

既存の型を壊さずに機能を追加できて、より柔軟な型定義が可能になる!

さいごに

次は、型エイリアスや型アサーションについて読んでみようと思います!

アドカレ2025が開催中! :christmas_tree:

今年もアドカレ開催中です :santa:
面白そうなカレンダーがたくさんです!

特設サイト ↓

ギフトカードや Airpods, iPadなど、豪華賞品すぎるプレゼントカレンダーは必見!:eyes:

参考

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?