1
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】タグ付き(判別可能な)ユニオン型

Posted at

はじめに

この記事では、タグ付き(判別可能な)ユニオン型 (discriminated union) の概要を記載します。

通常のユニオン型

タグ付きユニオン型の説明の前に通常のユニオン型について、説明します。
ユニオン型では、型をパイプ (|) で繋げて表現します。

以下の AuthState では、status は必須、usermessage はオプショナルになっています。

sample.ts
type AuthState =
  | { status: string; user?: { id: string; name: string }; message?: string };

AuthState 型を利用して status に応じたメッセージを表示する関数を作成したい場合、オプショナルのプロパティの存在をチェックする条件文を書く必要があります。

sample.ts
function displayAuthMessage(state: AuthState): string {
  if (state.status === "unauthenticated") {
    return "You are not logged in.";
  }

  if (state.status === "authenticating") {
    return "Logging in... Please wait.";
  }

  if (state.status === "authenticated") {
    if (state.user) {
      return `Welcome back, ${state.user.name}!`;
    }
    return "Error: Missing user information.";
  }

  if (state.status === "error") {
    if (state.message) {
      return `Authentication failed: ${state.message}`;
    }
    return "Error: An unknown error occurred.";
  }

  // No exhaustive type checking
  return "Unknown state.";
}

ユースケースとして、status"authenticated" の時は必ず user が存在するとした場合、この分岐は冗長です。タグ付きユニオン型を使えば、この冗長性を解消できます。

オプショナルのプロパティの存在をチェックする条件文がないと型エラーになります。

image.png

タグ付きユニオン型

タグ付きユニオン型では、ユニオンに属するの各オブジェクトの型を区別するための「タグ」がつきます。

以下の AuthState では、status が「タグ」に該当します。

sample.ts
type AuthState =
  | { status: "unauthenticated" }
  | { status: "authenticating" }
  | { status: "authenticated"; user: { id: string; name: string } }
  | { status: "error"; message: string };

通常のユニオン型とは異なり、usermessage の存在チェックが不要になります。その結果、分岐処理が読みやすく、保守性も高くなります。

sample.ts
function displayAuthMessage(state: AuthState): string {
  switch (state.status) {
    case "unauthenticated":
      return "You are not logged in.";

    case "authenticating":
      return "Logging in... Please wait.";

    case "authenticated":
      return `Welcome back, ${state.user.name}!`;

    case "error":
      return `Authentication failed: ${state.message}`;

    default: {
      // Exhaustiveness check
      const _exhaustive: never = state;
      throw new Error(`Unhandled state: ${_exhaustive}`);
    }
  }
}

参考

1
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
1
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?