TypeScript Enum vs Union Type、どちらを使うべきか
問題
TypeScriptプロジェクトで定数の集合を定義する際、enumとunion typeのどちらを使うべきか悩むことがあります。チームによって規約も異なり、判断が難しいところです。
Enumの落とし穴
enum Status {
Active = 'ACTIVE',
Inactive = 'INACTIVE',
Pending = 'PENDING'
}
これがJavaScriptにコンパイルされると、以下のようなコードが生成されます。
var Status;
(function (Status) {
Status["Active"] = "ACTIVE";
Status["Inactive"] = "INACTIVE";
Status["Pending"] = "PENDING";
})(Status || (Status = {}));
ランタイムにオブジェクトが生成されます。バンドルサイズに影響し、tree-shakingもうまく機能しません。
解決方法:Union Type + as const
const STATUS = {
Active: 'ACTIVE',
Inactive: 'INACTIVE',
Pending: 'PENDING',
} as const;
type Status = typeof STATUS[keyof typeof STATUS];
// 結果: 'ACTIVE' | 'INACTIVE' | 'PENDING'
as constを付けることで、リテラル型として推論されます。ランタイムコードが最小限になり、tree-shakingも正常に動作します。
シンプルな場合は、直接union typeを使うだけで十分です。
type Direction = 'up' | 'down' | 'left' | 'right';
ポイント
enumはランタイムオブジェクトを生成し、バンドルサイズが増加しますconst enumはインライン化されますが、--isolatedModules環境(Vite、Next.jsなど)では使用できませんas const+ union typeがほとんどのケースでより適切ですenumが必要な場面:ビットフラグ演算やランタイムでの逆方向マッピングが必要な場合に限られます