TypeScript: シチュエーション別で見る、文字列列挙型と文字列リテラル型の使い分け
TypeScriptでは、文字列列挙型と文字列リテラル型という2つの型を使って、許可される値を制限することができます。どちらも似ていますが、いくつかの重要な違いがあります。
文字列列挙型は、enum
キーワードを使って定義されます。各メンバーは、文字列リテラルで表されます。
enum CardinalDirection {
North,
East,
South,
West,
}
この例では、CardinalDirection
という名前の列挙型が定義されています。この列挙型には、North
、East
、South
、West
という4つのメンバーがあります。
文字列リテラル型は、単一の文字列リテラルで表されます。
type Direction = "North" | "East" | "South" | "West";
主な違い
文字列列挙型と文字列リテラル型の主な違いは以下の3つです。
- 拡張性
文字列列挙型は、後から新しいメンバーを追加することができます。一方、文字列リテラル型は、定義時に指定された文字列リテラルのみを受け付けます。
- 型安全性
文字列列挙型は、型安全性が保証されています。つまり、列挙型に定義されていない値を代入することはできません。一方、文字列リテラル型は、型安全性が保証されていません。
- コード生成
文字列列挙型は、コンパイル時に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