TypeScript エンム: Object.values 関数を用いて文字列リテラル型連合を作成

2024-04-21

TypeScript エンムから文字列リテラル型連合を作成する方法

keyof 演算子を用いる方法

最も一般的な方法は、keyof 演算子を用いて、エンムのキー(定数名)から文字列リテラル型連合を作成する方法です。

enum Direction {
  North,
  South,
  East,
  West
}

type DirectionString = keyof Direction; // "North" | "South" | "East" | "West"

この例では、Direction エンムのキーを DirectionString という型の文字列リテラル型連合として定義しています。DirectionString 型の変数には、Direction エンムの値である "North", "South", "East", "West" のいずれかを代入することができます。

Object.values 関数を用いて、エンムの値から文字列リテラル型連合を作成する方法もあります。

enum Direction {
  North,
  South,
  East,
  West
}

type DirectionString = typeof Direction[keyof Direction]; // "North" | "South" | "East" | "West"

const directionStrings: DirectionString[] = Object.values(Direction); // ["North", "South", "East", "West"]

const アサーションを用いる方法

enum Direction {
  North,
  South,
  East,
  West
}

const directionStrings: "North" | "South" | "East" | "West" = Direction; // "North" | "South" | "East" | "West"

まとめ

TypeScript において、エンムから文字列リテラル型連合を作成する方法には、keyof 演算子を用いる方法、Object.values 関数を用いる方法、const アサーションを用いる方法の 3 種類があります。それぞれの方法にはメリットとデメリットがあるので、状況に応じて適宜選択しましょう。

メリット

  • エンムの値を文字列として直接使用できる
  • 型安全性が高い
  • エンムの値を変更するたびに、文字列リテラル型連合を変更する必要がある
  • コードが冗長になる



enum Direction {
  North,
  South,
  East,
  West
}

type DirectionString = keyof Direction; // "North" | "South" | "East" | "West"

function getDirectionString(direction: Direction): DirectionString {
  switch (direction) {
    case Direction.North:
      return "North";
    case Direction.South:
      return "South";
    case Direction.East:
      return "East";
    case Direction.West:
      return "West";
    default:
      throw new Error("Invalid direction");
  }
}

const northString: DirectionString = getDirectionString(Direction.North); // "North"
const southString: DirectionString = getDirectionString(Direction.South); // "South"
const eastString: DirectionString = getDirectionString(Direction.East); // "East"
const westString: DirectionString = getDirectionString(Direction.West); // "West"

Object.values 関数を用いる方法

enum Direction {
  North,
  South,
  East,
  West
}

type DirectionString = typeof Direction[keyof Direction]; // "North" | "South" | "East" | "West"

const directionStrings: DirectionString[] = Object.values(Direction); // ["North", "South", "East", "West"]

function isDirectionString(s: string): s is DirectionString {
  return directionStrings.includes(s);
}

const northString: DirectionString = "North"; // "North"
const southString: DirectionString = "South"; // "South"
const eastString: DirectionString = "East"; // "East"
const westString: DirectionString = "West"; // "West"
const invalidString: string = "Invalid"; // string

if (isDirectionString(invalidString)) {
  console.log("有効な方向文字列です:", invalidString);
} else {
  console.log("無効な方向文字列です:", invalidString);
}
enum Direction {
  North,
  South,
  East,
  West
}

const directionStrings: "North" | "South" | "East" | "West" = Direction; // "North" | "South" | "East" | "West"

function isDirectionString(s: string): s is DirectionString {
  return directionStrings === s;
}

const northString: DirectionString = "North"; // "North"
const southString: DirectionString = "South"; // "South"
const eastString: DirectionString = "East"; // "East"
const westString: DirectionString = "West"; // "West"
const invalidString: string = "Invalid"; // string

if (isDirectionString(invalidString)) {
  console.log("有効な方向文字列です:", invalidString);
} else {
  console.log("無効な方向文字列です:", invalidString);
}

これらのサンプルコードは、あくまでも参考例です。実際のコードでは、状況に応じて適宜変更してください。

補足

  • 上記のサンプルコードは、TypeScript 4.4.3 を使用して動作確認しています。
  • 上記のサンプルコードは、あくまでも基本的な使い方を示したものであり、すべての状況に適用できるわけではありません。
  • 詳細については、TypeScript の公式ドキュメントを参照してください。

https://tsdoc.org/




TypeScript エンムから文字列リテラル型連合を作成する方法: その他の方法

型ガードを用いる方法

enum Direction {
  North,
  South,
  East,
  West
}

type DirectionString = typeof Direction[keyof Direction]; // "North" | "South" | "East" | "West"

function isDirectionString(s: string): s is DirectionString {
  return Object.values(Direction).includes(s as Direction);
}

function getDirectionString(direction: Direction): DirectionString | undefined {
  if (isDirectionString(direction)) {
    return direction;
  } else {
    return undefined;
  }
}

const northString: DirectionString | undefined = getDirectionString(Direction.North); // "North"
const southString: DirectionString | undefined = getDirectionString(Direction.South); // "South"
const eastString: DirectionString | undefined = getDirectionString(Direction.East); // "East"
const westString: DirectionString | undefined = getDirectionString(Direction.West); // "West"
const invalidString: DirectionString | undefined = getDirectionString("Invalid"); // undefined

この例では、isDirectionString 関数と getDirectionString 関数を使用して、エンムの値が文字列リテラル型連合に属しているかどうかを判断しています。

型エイリアスとジェネリック型を用いる方法

enum Direction {
  North,
  South,
  East,
  West
}

type DirectionString<T extends Direction> = keyof T;

const directionStrings: DirectionString<Direction> = Direction; // "North" | "South" | "East" | "West"

この例では、DirectionString 型エイリアスとジェネリック型を使用して、エンムの型から文字列リテラル型連合を作成しています。

enum Direction {
  North,
  South,
  East,
  West
}

type DirectionString = typeof Direction[keyof Direction]; // "North" | "South" | "East" | "West"

function isDirectionString(s: string): s is DirectionString {
  return s in Direction;
}

const northString: DirectionString | undefined = (Direction.North as DirectionString); // "North"
const southString: DirectionString | undefined = (Direction.South as DirectionString); // "South"
const eastString: DirectionString | undefined = (Direction.East as DirectionString); // "East"
const westString: DirectionString | undefined = (Direction.West as DirectionString); // "West"
const invalidString: DirectionString | undefined = ("Invalid" as DirectionString); // undefined

この例では、in 演算子を使用して、エンムの値がエンムオブジェクトに含まれているかどうかを判断しています。

TypeScript エンムから文字列リテラル型連合を作成するには、様々な方法があります。それぞれの方法にはメリットとデメリットがあるので、状況に応じて適宜選択しましょう。

  • 理解が難しい
  • すべての状況に適用できるわけではない
  • 上記以外にも、TypeScript エンムから文字列リテラル型連合を作成する方法があります。
  • 最新の TypeScript の機能を使用している場合は、新しい方法が利用できる可能性があります。

typescript enums


テスト対象のクラスをモック化する:Angular / TypeScriptでプライベートメソッドをテストする方法

この方法は、テスト対象のクラスをモックし、プライベートメソッドへのアクセスを提供することで、プライベートメソッドをテストします。テスト対象のクラスをモックするためのモジュールを作成します。モックモジュールで、テスト対象のクラスをモックし、プライベートメソッドへのアクセスを提供します。...


ReturnType型ガードで戻り値の型を取得

上記コードでは、add関数はnumber型の引数2つを受け取り、number型の戻り値を持つ関数として定義されています。myAdd変数にはadd関数オブジェクトが代入されます。typeof addとtypeof myAddを実行すると、どちらも"function"という文字列が返されます。これは、typeof演算子が関数の型情報ではなく、関数オブジェクトそのものを返していることを示しています。...


カスタムコンポーネントと JSX で HTML を拡張:React、TypeScript、TSX を使った実践ガイド

HTML 要素は、Web アプリケーションの基盤となるものです。しかし、標準の HTML 要素では、常に必要な機能が提供されているわけではありません。そのような場合、HTML 要素を拡張することで、アプリケーションに必要な機能を追加することができます。...


Angular, TypeScript, RxJS で Observable をインポートする:知っておきたいポイント

Angular、TypeScript、RxJSを使用する際、Observableを適切にインポートすることは重要です。ここでは、状況に応じて最適なインポート方法をいくつかご紹介します。個別インポート必要なObservableとオペレータのみを個別にインポートする方法です。最も簡潔で、バンドルサイズを小さく抑えることができます。...


React.jsとTypeScriptで発生する"'React' was used before it was defined"エラーの解決方法

このエラーメッセージは、ReactJSプロジェクトでJavaScriptファイル内で React 変数を参照しようとしているが、その変数がまだ定義されていない場合に発生します。原因このエラーが発生する主な原因は以下の2つです。import 文の記述ミス...