TypeScript: EnumとUnionを使いこなして開発効率を向上させる
TypeScriptの列挙型(Enum)と共用体(Union)
答え: 状況によって異なります。どちらにも利点と欠点があり、使い分けが必要です。
共用体(Union)とは?
type MyUnion = number | string;
const myValue: MyUnion = 10; // 数値型
myValue = "Hello"; // 文字列型
列挙型(Enum)とは?
名前付きの定数を定義できる型です。例えば、以下のように、色の名前を列挙型で表現できます。
enum Color {
Red,
Green,
Blue
}
const myColor: Color = Color.Red; // "Red"
共用体と列挙型の比較
機能 | 共用体 | 列挙型 |
---|---|---|
型の安全性 | 高い | 高い |
読みやすさ | 状況による | 高い |
コード量 | 少ない | 多い |
機能 | 型ガードが必要 | 型ガードが不要 |
拡張性 | 高い | 低い |
共用体の利点
- 型ガードを使って、型の安全性も確保できる
- コード量が少なく、簡潔に記述できる
- 型ガードが必要
- 読みづらい場合がある
列挙型の利点
- 読みやすく、コードの意味が分かりやすい
- 拡張性が低い
- コード量が多くなる
使い分け
- 型安全性を重視する場合は、共用体と型ガードを組み合わせて使用するのがおすすめです。
- 値の数が多い場合や、動的に値を追加したい場合は、共用体の方がコード量が少なく、簡潔に記述できます。
- 値の数が少ない場合は、列挙型の方が読みやすく、コードの意味が分かりやすいのでおすすめです。
例
- ユーザーの入力値を表す場合は、共用体を使う
- 色を表す場合は、列挙型を使う
type MyUnion = number | string;
function printValue(value: MyUnion): void {
if (typeof value === "number") {
console.log(`数値: ${value}`);
} else {
console.log(`文字列: ${value}`);
}
}
const myValue1: MyUnion = 10;
printValue(myValue1); // 数値: 10
const myValue2: MyUnion = "Hello";
printValue(myValue2); // 文字列: Hello
列挙型
enum Color {
Red,
Green,
Blue
}
function printColor(color: Color): void {
switch (color) {
case Color.Red:
console.log("赤");
break;
case Color.Green:
console.log("緑");
break;
case Color.Blue:
console.log("青");
break;
}
}
const myColor: Color = Color.Red;
printColor(myColor); // 赤
共用体と型ガード
type MyUnion = number | string;
function isNumber(value: MyUnion): value is number {
return typeof value === "number";
}
function printValue(value: MyUnion): void {
if (isNumber(value)) {
console.log(`数値: ${value}`);
} else {
console.log(`文字列: ${value}`);
}
}
const myValue1: MyUnion = 10;
printValue(myValue1); // 数値: 10
const myValue2: MyUnion = "Hello";
printValue(myValue2); // 文字列: Hello
共用体と動的な値の追加
type MyUnion = number | string;
let myValue: MyUnion = 10;
// 動的に値を追加
myValue = "Hello";
console.log(myValue); // Hello
enum Color {
Red,
Green,
Blue
}
// 列挙型に動的に値を追加することはできない
// 例:
// Color.Purple = "Purple"; // エラーが発生する
TypeScriptでEnumとUnionを使う他の方法
discriminated union
discriminated union は、共用体の一種で、各メンバーに識別子プロパティを追加できます。識別子プロパティを使って、メンバーを判別できます。
interface MyUnion {
type: "number" | "string";
value: number | string;
}
function printValue(value: MyUnion): void {
switch (value.type) {
case "number":
console.log(`数値: ${value.value}`);
break;
case "string":
console.log(`文字列: ${value.value}`);
break;
}
}
const myValue1: MyUnion = { type: "number", value: 10 };
printValue(myValue1); // 数値: 10
const myValue2: MyUnion = { type: "string", value: "Hello" };
printValue(myValue2); // 文字列: Hello
discriminated union の利点:
- コードがより読みやすくなる
- 型安全性がより高くなる
readonly enum
readonly enum は、列挙型のメンバー値を変更できないようにするものです。
readonly enum Color {
Red = "red",
Green = "green",
Blue = "blue"
}
let myColor: Color = Color.Red;
// myColor = "purple"; // エラーが発生する
readonly enum の利点:
- 意図しない値の変更を防げる
- コードの安全性が高くなる
- 値を追加できない
enum member types
enum member types は、列挙型のメンバーに個別の型を指定できるものです。
enum Color {
Red = "red",
Green = "green",
Blue = "blue"
}
function getHexColor(color: Color): string {
switch (color) {
case Color.Red:
return "#ff0000";
case Color.Green:
return "#00ff00";
case Color.Blue:
return "#0000ff";
}
}
const redColor: Color.Red = Color.Red;
const hexColor = getHexColor(redColor); // "#ff0000"
// 他の色のメンバーは使用できない
// const greenColor: Color.Green = Color.Red; // エラーが発生する
typescript enums unions