TypeScriptにおいて列挙型(enum)は、関連する定数を一つのグループとしてまとめるための非常に強力な機能です。
開発を進める中で、通常のenumを使用するか、あるいはconst enumを使用するかで迷う場面は少なくありません。
これら二つは見た目こそ似ていますが、コンパイル後のJavaScriptコードや、実行時の挙動において決定的な違いが存在します。
本記事では、TypeScriptのenumとconst enumの根本的な違いを整理し、それぞれのメリット・デメリットを詳しく解説します。
2026年現在の開発トレンドも踏まえつつ、どちらを採用すべきかの具体的な判断基準を提示しますので、ぜひ参考にしてください。
TypeScriptにおけるenumの基本概念
まずは、TypeScriptの標準的なenumがどのようなものかをおさらいしておきましょう。
enumは、特定の名前を持つ定数の集合を定義するための仕組みです。
デフォルトでは数値ベースの列挙型として動作し、自動的に0から始まる連番が割り振られます。
// 標準的な数値列挙型の定義
enum UserRole {
Admin,
Editor,
Viewer
}
const role: UserRole = UserRole.Admin;
console.log(role);
0
このように、UserRole.Adminという名前でアクセスできますが、実体は数値の「0」として扱われます。
また、文字列を値として持つ「文字列列挙型」も頻繁に利用されます。
// 文字列列挙型の定義
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT"
}
console.log(Direction.Up);
"UP"
標準的なenumの最大の特徴は、コンパイル後もJavaScriptのオブジェクトとして実体が残る点にあります。
const enumの仕組みと特徴
一方で、const enumはパフォーマンスを重視して設計された特別な列挙型です。
宣言の先頭にconstキーワードを付与することで定義します。
// const enumの定義
const enum Status {
Active,
Inactive,
Pending
}
const currentStatus = Status.Active;
const enumが標準のenumと決定的に異なるのは、コンパイル時にすべてインライン展開されるという点です。
つまり、コンパイル後のJavaScriptにはStatusというオブジェクト自体が存在しなくなります。
参照箇所は、すべて直接的なリテラル(数値や文字列)に置き換わります。
生成されるJavaScriptコードの比較
実際にコンパイル結果を比較することで、その違いをより明確に理解できます。
1. 標準のenumの場合
enum Color {
Red,
Blue
}
const myColor = Color.Red;
上記のコードをコンパイルすると、以下のようなJavaScriptが生成されます。
var Color;
(function (Color) {
Color[Color["Red"] = 0] = "Red";
Color[Color["Blue"] = 1] = "Blue";
})(Color || (Color = {}));
var myColor = Color.Red;
このように、即時関数(IIFE)を用いてオブジェクトが生成されていることがわかります。
2. const enumの場合
const enum Color {
Red,
Blue
}
const myColor = Color.Red;
これに対し、const enumの場合は次のようなJavaScriptになります。
var myColor = 0 /* Red */;
定義そのものが消滅し、参照していた箇所が直接数値の0に書き換わっています。
これにより、実行時のメモリアクセス負荷が減り、バンドルサイズも削減されるという大きなメリットが生まれます。
逆引き(リバースマッピング)の有無
標準のenumとconst enumのもう一つの重要な違いは、逆引き(Reverse Mapping)が可能かどうかです。
逆引きとは、値(数値)からその名前(キー名)を取得する機能のことを指します。
enum UserStatus {
Offline = 0,
Online = 1
}
// 値からキー名を取得
console.log(UserStatus[1]);
"Online"
標準の数値列挙型ではこのようにキー名を取得できますが、const enumではこれができません。
なぜなら、コンパイル後のコードにオブジェクトが存在しないため、ルックアップを行うためのマップが存在しないからです。
デバッグ時やログ出力などで「この数値がどのステータスを指しているか」を名前で確認したい場合には、標準のenumが有利です。
主要な違いのまとめ表
ここで、両者の違いを表にまとめて整理します。
| 機能・特徴 | 標準の enum | const enum |
|---|---|---|
| コンパイル後の実体 | JavaScriptオブジェクトとして残る | 完全に消滅する(インライン展開) |
| 逆引き(Reverse Mapping) | 可能(数値列挙型のみ) | 不可能 |
| 実行時のパフォーマンス | オブジェクト参照のオーバーヘッドあり | リテラル置換のため非常に高速 |
| バンドルサイズ | わずかに大きくなる | 最小限に抑えられる |
| 外部ライブラリ公開時の制限 | 特になし | 消費側で不整合が起きるリスクがある |
const enumを使用する際の注意点
パフォーマンス面で優れたconst enumですが、使用にはいくつかの注意点があります。
1. 孤立したモジュール(isolatedModules)の影響
Viteやesbuildなどのモダンなビルドツールを使用している場合、TypeScriptの設定(tsconfig.json)でisolatedModules: trueが設定されていることが多いです。
この環境下では、ファイルごとのコンパイルが行われるため、const enumのインライン展開が正しく機能しない場合があります。
そのため、プロジェクト全体でモダンなツールチェーンを採用している場合は、const enumの使用を避けるか、ビルドツールの制約を理解しておく必要があります。
2. ライブラリ開発における互換性
npmパッケージなどのライブラリを公開する場合、const enumの使用には注意が必要です。
ライブラリを消費する側のプロジェクトが異なるTypeScriptの設定でビルドされていると、実行時に参照エラーが発生する可能性があります。
外部に提供する公開APIの定義には、標準のenumまたはオブジェクト定数を用いるのが安全です。
3. preserveConstEnumsフラグ
どうしてもインライン展開の恩恵を受けつつ、オブジェクトとしての実体も残したい場合には、preserveConstEnumsオプションを有効にすることができます。
このオプションを有効にすると、const enumであってもコンパイル後にオブジェクトの定義が生成されます。
ただし、この場合は本来の「インライン展開による最適化」という目的が半分失われるため、慎重な検討が必要です。
使い分けの判断基準
実際の開発現場では、以下の基準に基づいて使い分けることをお勧めします。
標準のenumを選択すべきケース
- 実行時に数値から名前を逆引きしたい場合。
- 外部に公開するライブラリの型定義として使用する場合。
- 動的なキーアクセス(
Enum[key]のような形式)が必要な場合。 - デバッグのしやすさを最優先したい場合。
const enumを選択すべきケース
- アプリケーション内部だけで完結する定数定義の場合。
- パフォーマンスを極限まで追求する必要があるループ処理内などで参照する場合。
- バンドルサイズを少しでも削減したいモバイルWebアプリなどの開発。
- コンパイル後のコードを極力シンプルに保ちたい場合。
代替案としての「as const」オブジェクト
近年のTypeScript開発では、enumの代わりとしてas const(Const Assertions)を用いたオブジェクト定数が好まれる傾向にあります。
これは、enum特有の複雑な挙動を避けつつ、型安全性を確保できるためです。
// as const を使った代替案
const APP_STATUS = {
ACTIVE: 'active',
INACTIVE: 'inactive'
} as const;
// 型として抽出
type AppStatus = typeof APP_STATUS[keyof typeof APP_STATUS];
const myStatus: AppStatus = APP_STATUS.ACTIVE;
この手法は、JavaScriptの標準的な挙動に基づいているため予測可能性が高く、Tree Shakingとの相性も良いため、多くのフロントエンド開発現場で採用されています。
enumやconst enumの使い分けに迷い、かつそれらの特殊な挙動が不要であれば、このas constパターンを検討するのも一つの手です。
まとめ
TypeScriptのenumとconst enumは、目的や用途に応じて使い分けるべき重要なツールです。
標準のenumは、実体としてのオブジェクトと逆引き機能を持ち、安定した動作を提供します。
対してconst enumは、インライン展開による圧倒的なランタイムパフォーマンスと軽量化を実現しますが、逆引きができずビルド環境に依存するという制約があります。
それぞれの特性を正しく理解し、プロジェクトの規模や構成に合わせて最適な選択を行ってください。
特にモダンな開発環境においては、今回紹介したas constによる代替案も含めて検討することで、よりメンテナンス性の高いコードを記述できるようになります。
TypeScriptの型システムを最大限に活かし、効率的で堅牢なアプリケーション開発を目指しましょう。
