TypeScript

TypeScriptでSwitch/Case文を書こう|コード例付き

(最終更新月:2023年12月)

✔以下のような疑問を持っている方に向けて書かれています

「TypeScriptとは具体的にどのようなものなのだろうか?」

「どうやってTypeScriptのコードを書いていけばいいのだろうか?」

「実際にどのようなTypeScriptのコードが利用されているのを見てみたい。」

✔当記事では下記の内容を提供します。

  • TypeScriptの基本的な概念
  • TypeScriptのコードを書く際の基本的な構文とその応用方法
  • 実際に使用されているTypeScriptのコード例

当記事を読み進めることで、TypeScriptの基礎から、より実践的なコードの書き方までを、実例を交えて深く理解できるようになります。

始めから終わりまで、ぜひ注意深く読んでTypeScriptの知識を深めていきましょう。

TypeScriptとswitch文の基礎

こちらでは、TypeScriptとswitch文の基礎についてお伝えしていきます。

TypeScriptとswitch文の基礎を理解することで、コードの可読性と保守性の向上に役立つでしょう。

  • TypeScriptの基本理解
  • switch文の基本構文
  • switch文の流れと動作

TypeScriptの基本理解

TypeScriptは、JavaScriptに型システムを追加したプログラミング言語です。

コンパイル時にエラーチェックをおこなうことで、実行時のバグを減らせます。

例えば、変数に予め型を指定することにより、以下のコードのように型安全なプログラミングが実現できます。

let count: number = 1; // 数値型を指定
count = 'hello'; // エラー: 型 'string' を型 'number' に割り当てることはできません。

このようにTypeScriptでは、変数、関数の引数、戻り値に型を定義することで、コードの安全性を高めています。

switch文の基本構文

switch文は、特定の変数の値に基づいて、複数のケースから実行するコードブロックを選択するための構文です。

基本的な構造は以下のとおりです。

let value: any = /* 何らかの値 */;
switch (value) {
  case 'firstCase':
    // valueが'firstCase'の場合に実行されるブロック
    break;
  case 'secondCase':
    // valueが'secondCase'の場合に実行されるブロック
    break;
  default:
    // どのcaseにも該当しない場合に実行されるブロック
}

この基本構文に従って、特定の値に応じた処理を実装することが可能です。

switch文の流れと動作

switch文の動作は、指定された変数の値とcase文で指定された値を比較し、一致するものがあれば、そのcaseブロックを実行します。

一致するcaseが存在しない場合は、defaultブロックを実行。

各ケースはbreak;文で区切られることが一般的で、これによりswitch文から抜け出します。

switch (grade) {
  case 'A':
    console.log('Excellent!');
    break;
  case 'B':
    console.log('Good job');
    break;
  case 'C':
    console.log('Passed');
    break;
  default:
    console.log('Try again');
}

grade'A'の場合「Excellent!」、'B'の場合「Good job」、それ以外の場合は「Try again」と出力します。

ケースはbreak文で終了しているため、一致したケースのみ実行され、続くケースは走らないのが通常の流れです。

switch文で厳密な条件分岐を行う

こちらでは、TypeScriptのswitch文を使って厳密な条件分岐をどのようにおこなうかを見ていきましょう。

厳密な条件分岐の理解と実装は、エラーの発生を減らし、予想外の挙動を避けることにつながります。

  • 厳密比較の仕組みと利点
  • 条件分岐のパターン例
  • 厳密等価演算を用いたコーディング例

厳密比較の仕組みと利点

TypeScriptでは、switch文でおこなわれる比較演算は「厳密等価」(===)が使われます。

これは型変換を伴わない比較であり、例えば数値の5と文字列の’5’は異なるものとして扱われます。

厳密等価による比較の例は、以下のとおりです。

let num: number = 5;
switch (num) {
  case 5:
    console.log('Number is 5');
    break;
  case '5':
    // このケースは実行されない
    console.log('String is 5');
    break;
}

厳密比較を使用するメリットは、型の違いによる予期しないバグを防ぐことができる点にあります。

条件分岐のパターン例

条件分岐においては、場合によっては複数のケースに一致できます。

以下がその一例です。

switch (status) {
  case 'pending':
  case 'processing':
    console.log('Order is being processed');
    break;
  case 'shipped':
  case 'delivered':
    console.log('Order is on its way');
    break;
  default:
    console.log('Unknown order status');
}

status'pending''processing'のいずれかの場合に同じメッセージが、'shipped''delivered'の場合には別の共通メッセージが出力されるようになっています。

複数のケースに対して同じ処理をおこないたい場合には、break文を挿入せずにケースラベルを続けて記述することで実現できます。

厳密等価演算を用いたコーディング例

厳密等価演算を用いたswitch文のコーディング例を見てみましょう。

例えば、異なる役職の社員に適切なアクションを割り当てる状況を考えます。

enum Role { Employee, Manager, Executive }

function getAction(role: Role): string {
  switch (role) {
    case Role.Employee:
      return 'Creating reports';
    case Role.Manager:
      return 'Managing teams';
    case Role.Executive:
      return 'Making decisions';
    default:
      throw new Error('Invalid role');
  }
}

let action = getAction(Role.Manager); // 'Managing teams'

Roleという列挙型(Enums)を定義し、それを使って関数getActionを実装しています。

各役職に応じたアクション文字列を返し、厳密等価演算は型安全性を保証しているため、誤った値(列挙型以外の値)が入力された場合はエラーを投げます。

switch文の応用テクニック

switch文をさらに強力に活用するための応用テクニックについて紹介していきます。

このテクニックをマスターすることで、よりアドバンスドなコードを書くことが可能です。

  • フォールスルーとは何か
  • フォールスルーの活用シナリオ
  • 列挙型(Enums)との組み合わせ方法

フォールスルーとは何か

switch文のフォールスルー(fallthrough)は、ケースの終わりにbreakを置かずに次のケースに処理を流すこと

これを意図的に活用することで、複数のケースで共通の処理を実行できますが、意図せずにフォールスルーしてしまうとバグの原因にもなります。

以下がフォールスルーの例です。

let product = 'cake';

switch (product) {
  case 'cake':
  case 'cookie':
    console.log('This is a dessert');
    // ここにbreakがないため、次のケースにフォールスルーする
  case 'bread':
    console.log('This is a bakery product');
    break;
  default:
    console.log('Unknown product');
}

product'cake'または'cookie'の場合、両方ともデザートであるとして最初のメッセージを出力した後、breakがないためパン製品に関するメッセージも出力します。

フォールスルーの活用シナリオ

フォールスルーを活用することで、効率的なコードの記述が可能になりますが、“意図的なフォールスルー”は慎重におこなう必要があります。

例えば、特別なイベントにおける重要度の高い顧客への対応を考えてみましょう。

enum CustomerStatus { New, Regular, VIP, SuperVIP }

function handleCustomer(status: CustomerStatus) {
  switch (status) {
    case CustomerStatus.VIP:
      giveDiscount();
      // VIPはSuperVIPの恩恵も受けるのでフォールスルー
    case CustomerStatus.SuperVIP:
      giveAccessToLounge();
      break;
    case CustomerStatus.New:
    case CustomerStatus.Regular:
      thankYouMessage();
      break;
  }
}

このシナリオではVIP顧客には割引があり、フォールスルーを利用してSuperVIP顧客には追加のラウンジアクセスを提供しています。

一方、新規顧客とリピーター顧客には、共通の感謝のメッセージを表示する処理がおこなわれます。

列挙型(Enums)との組み合わせ方法

TypeScript では列挙型(Enums)と switch 文を組み合わせて使用することで、限定された値セットに対する処理を効率良く記述することが可能です。

以下に列挙型と switch 文を組み合わせた例を示します。

enum Direction { Up, Down, Left, Right }

function move(direction: Direction) {
  switch (direction) {
    case Direction.Up:
      console.log('Moving up');
      break;
    case Direction.Down:
      console.log('Moving down');
      break;
    case Direction.Left:
      console.log('Moving left');
      break;
    case Direction.Right:
      console.log('Moving right');
      break;
  }
}

move(Direction.Left); // 'Moving left' と出力される

Direction列挙型を定義し、それぞれの方向に対して異なる処理をおこなっています。

列挙型を使用することで、コードの意図が明確になり、エラーの可能性も低減されます。

高度なケース処理パターン

switch文を活用した高度なケース処理について学んでいきます。

より複雑な状況に対応するためのテクニックを習得することで、プログラムの可能性を広げられるでしょう。

  • 完全性チェックの実装方法
  • 高度なswitch文とユニオン型
  • パターンマッチングの利用

完全性チェックの実装方法

TypeScript では、switch 文で列挙型を使用する際に、すべてのケースが網羅されているかをチェックする「完全性チェック」(Exhaustiveness checking)をおこなうことがひとつのベストプラクティスとされています。

これにより、未扱いのケースが存在しないことをコンパイラレベルで保証できるのです。

以下のコードは、完全性チェックの一例です。

enum Response {
  No, 
  Yes, 
  Maybe
}

function respond(message: Response) {
  switch (message) {
    case Response.No:
      console.log('Responded No');
      break;
    case Response.Yes:
      console.log('Responded Yes');
      break;
    case Response.Maybe:
      console.log('Responded Maybe');
      break;
    default:
      const exhaustiveCheck: never = message;
      console.log(exhaustiveCheck); // Errorが発生するはずがない
      break;
  }
}

respond(Response.Yes); // 'Responded Yes' と出力される

defaultのケースでnever型の変数に代入しようとすることで、messageResponse列挙型のいずれかの値でない場合、コンパイル時にエラーが発生するようにします。

列挙型の値が追加された場合にも、その値を扱うケースを追加する必要があることを思い出させることができます。

高度なswitch文とユニオン型

TypeScriptのユニオン型を使用することで、異なる型を持つ変数をひとつの変数に統合し、switch文でその型に応じた処理をおこなえます。

以下がその使用例です。

type Action = 'drive' | 'fly' | 'sail';

function performAction(action: Action) {
  switch (action) {
    case 'drive':
      console.log('Driving...');
      break;
    case 'fly':
      console.log('Flying...');
      break;
    case 'sail':
      console.log('Sailing...');
      break;
  }
}

performAction('sail'); // 'Sailing...' と出力される

この例では、'drive''fly''sail'という文字列リテラルからなるユニオン型Actionを使用しています。

switch文内でAction型のactionに応じた適切な出力をおこなっています。

パターンマッチングの利用

TypeScriptでは、パターンマッチングを用いて、より複雑な条件を簡潔に表現できます。

パターンマッチングは、特定のデータ構造や値に基づいて異なる処理を実行する際に有効です。

例えば、以下のように複数の値に対して異なる処理を行う場合に利用できます。

type Shape = 'circle' | 'square' | 'triangle';

function calculateArea(shape: Shape, dimensions: number): number {
    switch (shape) {
        case 'circle':
            return Math.PI * dimensions * dimensions;
        case 'square':
            return dimensions * dimensions;
        case 'triangle':
            // 三角形の面積の計算
            return dimensions * dimensions * Math.sqrt(3) / 4;
        default:
            throw new Error('不明な形状');
    }
}

TypeScriptの型システムと組み合わせることで、より表現力の高いコードを記述することが可能です。

ケース別のサンプルとその解説

こちらでは、ケース別のサンプルをご覧いただきます。

  • シンプルな条件のサンプルコード詳細
  • 複雑なロジック処理のサンプルコード
  • 実世界のケーススタディ

シンプルな条件のサンプルコード詳細

TypeScriptでのシンプルな条件分岐を実装するためのサンプルコードは、初学者にとって理解しやすい良い出発点です。

例えば、以下のようなコードは、基本的なswitch文の使用方法を示しています。

const fruit = 'apple';

switch (fruit) {
    case 'apple':
        console.log('りんごです');
        break;
    case 'banana':
        console.log('バナナです');
        break;
    default:
        console.log('その他の果物です');
}

ここでは、文字列の値に基づいて異なるメッセージを表示しています。

複雑なロジック処理のサンプルコード

複雑なロジックを含む条件分岐を実装する際には、switch文が非常に役立ちます。

例えば、異なるユーザータイプに基づいて異なるアクションを取る場合などがその例です。

以下に、そのようなシナリオのコード例を示します。

type UserType = 'admin' | 'user' | 'guest';

function handleUserAction(userType: UserType): void {
    switch (userType) {
        case 'admin':
            // 管理者用のアクション
            break;
        case 'user':
            // 一般ユーザー用のアクション
            break;
        case 'guest':
            // ゲストユーザー用のアクション
            break;
    }
}

このようなコードは、異なるユーザータイプに対して適切な処理を分岐させるのに適しています。

実世界のケーススタディ

実世界のアプリケーションにおけるswitch文の使用例を検討することで、TypeScriptのswitch文の理解を深められます。

ウェブアプリケーションにおけるルーティング処理や、ゲーム開発におけるキャラクターの状態管理などが考えられるでしょう。

これらのケーススタディを通じて、switch文がどのように複雑なロジックを管理し、コードの可読性を向上させるかを理解できます。

switch文のエラーハンドリングとデバッグ

こちらでは、switch文のエラーハンドリングとデバッグについてご覧いただきます。

  • エラーハンドリングの技法
  • 共通のエラーとデバッグ手法
  • テストとリファクタリングのベストプラクティス

エラーハンドリングの技法

TypeScriptのswitch文において、エラーハンドリングは重要な役割を果たします。

とくにdefaultケースは、想定外の入力やエラー状況に対処するための安全策として機能するので重要です。

エラーを投げる(throw)ことで、エラーが発生した際に即座に対処し、問題の特定を容易にします。

以下はエラーハンドリングの一例です。

function processCommand(command: string): void {
    switch (command) {
        case 'start':
            // 処理
            break;
        case 'stop':
            // 処理
            break;
        default:
            throw new Error(`未知のコマンド: ${command}`);
    }
}

この方法では、不正または未知のコマンドが入力された場合にエラーを投げることで、迅速に対応できます。

共通のエラーとデバッグ手法

TypeScriptでswitch文を使用する際に遭遇する一般的なエラーには、以下のようなものがあります。

  • 間違ったケースラベルの使用
  • breakステートメントの忘れ

これらのエラーをデバッグするためには、コードを段階的に実行し、各ケースが期待どおりに動作するかの確認が効果的です。

開発ツールのコンソールログやブレークポイントを使用することで、コードの実行フローを詳細に追跡できます。

テストとリファクタリングのベストプラクティス

switch文を含むTypeScriptコードの品質を保つためには、単体テストとリファクタリングが不可欠です。

単体テストにより、各ケースが正しく動作することを保証し、リファクタリングにより、コードの可読性とメンテナンスの容易さを高められます。

特に複雑なswitch文では、コードの簡潔さを保ちながら、可読性と機能性を両立させることが重要です。

よくある疑問

TypeScriptのswitch文について、よくある疑問をまとめました。

  • breakの意味と省略の影響
  • TypeScriptとJavaScriptのswitch文の違い
  • 効率的なケース処理のコツ

breakの意味と省略の影響

breakステートメントは、switch文の各ケースが終了したことを示し、次のケースに流れ落ちる(fall through)のを防ぐもの。

breakを省略すると、次のケースにコードの実行が続行されるため、意図しない動作が発生する可能性があります。

TypeScriptとJavaScriptのswitch文の違い

TypeScriptのswitch文は基本的にJavaScriptのそれと同じですが、TypeScriptでは型の厳密性が加わります。

特定の型の値にのみケースを適用するなど、より安全で予測可能なコードを書くことが可能です。

効率的なケース処理のコツ

効率的なケース処理のためには、ケースを明確にし、可能な限り単純に保つことが重要です。

また、共通の処理は関数に抽出し、重複を避けることで、コードの管理が容易になります。

まとめ

当記事では、TypeScriptのswitch文について学習してきました。

TypeScriptでswitch文を効果的に使用するには、以下が重要です。

  • 明確な条件分岐
  • 適切なエラーハンドリング
  • コードの可読性と管理のしやすさを保つ

これらの要素をバランス良く取り入れることで、機能的かつ保守しやすいコードを作成できます。

TypeScriptのswitch文に関するさらなる理解を深めるためには、公式ドキュメント、オンラインチュートリアル、コミュニティフォーラムなどのリソースを活用することが有効です。

これらの知識を活用し、実践的なコーディングスキルを磨くことで、TypeScriptにおけるより効果的なプログラミングを実現できるでしょう。