はじめに
「読んで学ぶTypeScript」をちょっとずつ読み進めます!
今回は、列挙型 (enum) についてです!
コーディングに慣れていないので、ところどころ用語を調べて記載しながら書きますmm
そのため、初心者の方が理解するには、助けになるかもしれません ![]()
既存の型だけでは不便なことがある
TypeScriptには、stringやnumberなどのプリミティブ型以外に、それらを組み合わせてより複雑なデータを表現する機能があるらしいです。
今回はそれらの一つである列挙型について学びます ![]()
列挙型 (enum)
列挙型 (enum)とは
- 定数をひとまとめにするための機能
列挙型の書き方
-
enumの後に列挙型名とメンバーを書く - 任意の文字列 or 数値を、定数の値として割り当てることができる
- 定義時に値を指定しなかった場合、0から順に値が自動で設定される
- 以下の例なら、Top: 0, Right: 1, Bottom: 2, Left: 3
- 定義時に値を指定しなかった場合、0から順に値が自動で設定される
enum Position {
// ^^^列挙型名
Top, // メンバー
Right, // メンバー
Bottom, // メンバー
Left, // メンバー
}
列挙型が便利な場面
誤入力しやすい文字列の代わりに、厳密な値のセットを定義できる
// 文字列列挙型を定義
export enum Theme {
LIGHT = "light",
DARK = "dark",
SYSTEM = "system"
}
// enumを使用する関数
function applyTheme(selectedTheme: Theme): void {
// switch文で厳密な値の比較
switch (selectedTheme) {
case Theme.LIGHT:
console.log("ライトテーマを適用しました。");
break;
case Theme.DARK:
console.log("ダークテーマを適用しました。");
break;
case Theme.SYSTEM:
console.log("システム設定に従ったテーマを適用しました。");
break;
}
}
関数に渡せる値が定義された定数に限定され、タイプミスによる実行時エラーを防げる
数値列挙型は、サーバーからのステータスコードやフラグを扱う際にも便利↓
// 数値列挙型を定義
export enum HttpStatusCode {
OK = 200,
BAD_REQUEST = 400,
UNAUTHORIZED = 401,
INTERNAL_SERVER_ERROR = 500
}
// enumを使用する関数
function handleResponse(code: HttpStatusCode, message: string): void {
if (code >= 400) {
console.error(`エラーが発生しました: [${code}] ${message}`);
} else if (code === HttpStatusCode.OK) {
console.log(`成功: [${code}] ${message}`);
}
}
数値の代わりに意味のある名前を使えるため、コードが読みやすくなる
列挙型の問題点
便利そうな機能ですが、列挙型 (enum)はいくつか問題点があるようです
1. JavaScriptの仕様から離れすぎている
- 基本TypeScriptは、JavaScriptを型の世界に限って拡張する思想
- コンパイル後も消えずにJavaScriptのオブジェクトとして残る特殊な機能
- 通常、TypeScriptの型は、JavaScriptに変換されると残らない
参考(TypeScriptのコードが実行される流れ)
- enum構文が、JavaScriptの言語仕様にないため、コンパイル後に記述量が増える
コードサイズ増加・パフォーマンス低下や、意図しない挙動が起こる原因にもなり得る
2. 型安全上の問題
- 数値列挙型は、TypeScript 5.0未満だと、number型なら何でも代入できてしまう
- TypeScript 5.0以降では、この問題が大幅に解消され、列挙型メンバーの値以外の値を代入しようとするとエラーになる
3. 文字列列挙型は公称型に近い振る舞いをする
公称型とは?
-
名前が同じ型同士しか互換性がないと判断される型
- 通常、TypeScriptのほとんどの型は、中身の構造が同じであれば、型名が違っても互換性があると見なされる(構造的部分型)
// 例
enum StringEnum {
Foo = "foo",
}
const foo1: StringEnum = StringEnum.Foo;
// StringEnum型から取得した値(StringEnum型)なので、互換性がありコンパイルが通る
const foo2: StringEnum = "foo";
// 値は同じ"foo"だが、ただの文字列として判断される
// StringEnum型とは互換性がないため、エラーになる
さいごに
今回は、列挙型の特徴・メリットと問題点を学びました ![]()
列挙型の代替手段としてユニオン型が挙げられていたので、
次は、ユニオン型・インターセクション型について読んでみようと思います!
アドカレ2025が開催中!
今年もアドカレ開催中です ![]()
面白そうなカレンダーがたくさんです!
特設サイト ↓
ギフトカードや Airpods, iPadなど、豪華賞品すぎるプレゼントカレンダーは必見!
↓
参考
