TypeScript: シチュエーション別で見る、文字列列挙型と文字列リテラル型の使い分け

2024-04-11

TypeScriptでは、文字列列挙型と文字列リテラル型という2つの型を使って、許可される値を制限することができます。どちらも似ていますが、いくつかの重要な違いがあります。

文字列列挙型は、enum キーワードを使って定義されます。各メンバーは、文字列リテラルで表されます。

enum CardinalDirection {
  North,
  East,
  South,
  West,
}

この例では、CardinalDirection という名前の列挙型が定義されています。この列挙型には、NorthEastSouthWest という4つのメンバーがあります。

文字列リテラル型は、単一の文字列リテラルで表されます。

type Direction = "North" | "East" | "South" | "West";

主な違い

文字列列挙型と文字列リテラル型の主な違いは以下の3つです。

  1. 拡張性

文字列列挙型は、後から新しいメンバーを追加することができます。一方、文字列リテラル型は、定義時に指定された文字列リテラルのみを受け付けます。

  1. 型安全性

文字列列挙型は、型安全性が保証されています。つまり、列挙型に定義されていない値を代入することはできません。一方、文字列リテラル型は、型安全性が保証されていません。

  1. コード生成

文字列列挙型は、コンパイル時にJavaScriptのオブジェクトに変換されます。一方、文字列リテラル型は、そのままJavaScriptコードに埋め込まれます。

使い分け

  • 拡張性が必要な場合は、文字列列挙型を使用します。
  • コードサイズを小さくしたい場合は、文字列リテラル型を使用します。

補足

  • TypeScript 4.0以降では、const enum キーワードを使って、文字列列挙型の値を定数として宣言することができます。
  • 文字列列挙型と文字列リテラル型のどちらを使用するかは、状況によって異なります。

// 文字列列挙型

enum Color {
  Red,
  Green,
  Blue,
}

const color: Color = Color.Red;

// 文字列リテラル型

type Size = "small" | "medium" | "large";

const size: Size = "medium";

文字列列挙型と文字列リテラル型は、どちらも許可される値を制限するために使用することができます。それぞれの特徴を理解し、状況に応じて使い分けることが重要です。




文字列列挙型

// 定義
enum CardinalDirection {
  North,
  East,
  South,
  West,
}

// 使用
function getDirection(direction: CardinalDirection): string {
  switch (direction) {
    case CardinalDirection.North:
      return "北";
    case CardinalDirection.East:
      return "東";
    case CardinalDirection.South:
      return "南";
    case CardinalDirection.West:
      return "西";
  }
}

// 例
const direction = CardinalDirection.East;
const directionText = getDirection(direction);
console.log(directionText); // 出力: 東

文字列リテラル型

// 定義
type Size = "small" | "medium" | "large";

// 使用
function getSizeDescription(size: Size): string {
  switch (size) {
    case "small":
      return "小さい";
    case "medium":
      return "中くらい";
    case "large":
      return "大きい";
  }
}

// 例
const size = "medium";
const sizeDescription = getSizeDescription(size);
console.log(sizeDescription); // 出力: 中くらい
  • 文字列列挙型と文字列リテラル型は、どちらも型エイリアスと組み合わせて使用することができます。



文字列列挙型と文字列リテラル型の代替案

オブジェクトリテラルを使って、文字列値の集合を定義することができます。

const CardinalDirection = {
  North: "北",
  East: "東",
  South: "南",
  West: "西",
};

// 使用
const direction = CardinalDirection.East;
const directionText = CardinalDirection[direction];
console.log(directionText); // 出力: 東

Union型を使って、複数の文字列リテラルを組み合わせることができます。

type Direction = "North" | "East" | "South" | "West";

// 使用
const direction: Direction = "East";
const directionText = direction;
console.log(directionText); // 出力: 東

関数を使って、文字列値の検証を行うことができます。

function isValidDirection(direction: string): boolean {
  return ["North", "East", "South", "West"].includes(direction);
}

// 使用
const direction = "East";
const isValid = isValidDirection(direction);
console.log(isValid); // 出力: true

それぞれの方法の比較

方法メリットデメリット
文字列列挙型型安全性が保証されているコードサイズが大きくなる
文字列リテラル型コードサイズが小さくなる型安全性が保証されていない
オブジェクトリテラル柔軟性が高い型安全性が曖昧
Union型型安全性が保証されているコードが冗長になる
関数柔軟性が高いコードが複雑になる
  • 柔軟性が必要であれば、オブジェクトリテラルまたは関数を使用します。

typescript


インターフェース、型パラメーター、型ガードも活用!TypeScriptで基底クラスのメンバーにアクセスする

基底クラスのメンバーには、以下の2種類があります。プロパティ: データを表す変数のようなものです。メソッド: 処理を実行する関数のようなものです。基底クラスのメンバーにアクセスする場所は、以下の2つが考えられます。派生クラス: 基底クラスを継承したクラスです。...


TypeScriptにおける'any'と'Object': 徹底解説

この型システムにおいて、'any'と'Object'は重要な型です。しかし、それぞれ異なる性質を持ち、使い分けが重要です。'any'型は、あらゆる型の値を受け入れる型です。これは、型安全性を犠牲にして、柔軟性を高める場合に使用されます。例:...


【保存版】Angular、TypeScript、RxJSで発生するrxjs/Subject.d.tsエラー:原因、対策、回避策を完全網羅

このエラーは、TypeScript 2.4 以降で RxJS 5.5 以前を使用している場合に発生します。RxJS 5.5 以降では、Subject クラスの lift プロパティの型が変更されましたが、rxjs/Subject. d.ts ファイルの型定義は古いままになっています。そのため、TypeScript コンパイラは、Subject クラスが Observable クラスを誤って拡張しているというエラーを出力します。...


React + TypeScript で発生するエラー「Binding element 'children' implicitly has an 'any' type.ts(7031)」の原因と解決策

Reactアプリケーションを TypeScript で開発していると、Binding element 'children' implicitly has an 'any' type. ts(7031) というエラーが発生することがあります。これは、JSX 要素の children プロパティに渡される値の型が TypeScript コンパイラによって正しく推論できないことを示しています。...


【保存版】TypeScript, ts-node, ts-node-devで発生する「False expression: Non-string value passed to ts.resolveTypeReferenceDirective in typescript」エラー:もう悩まない!原因と解決策を徹底解説

このエラーは、TypeScript 関係のツール (TypeScript、ts-node、ts-node-dev) を使用している際に発生する可能性があります。エラーメッセージは "False expression: Non-string value passed to ts...