てらブログ

てらブログ

日々の学習の備忘録

enumは使わずにas const等でreadonlyのconstを作成することについて

TypeScriptのEnumについて

enumとは

enumは、関連する定数のグループを一緒に束ねるための機能。たとえば、以下のようにenumを使用することで、特定の集合の値(この場合は方角)を表すことができる。

enum Direction {
  Up,
  Down,
  Left,
  Right
}

enumはいくつかの問題点を抱えている。例えば、生成されるJavaScriptが予想外の挙動を示すことがあったり、enum内の値が実行時に変更可能であるなどの問題がある。

生成されるJavaScriptが想定外の挙動を示す:

enum Colors {
  Red,
  Green,
  Blue
}

上記がJSにコンパイルされると

var Colors;
(function (Colors) {
  Colors[Colors["Red"] = 0] = "Red";
  Colors[Colors["Green"] = 1] = "Green";
  Colors[Colors["Blue"] = 2] = "Blue";
})(Colors || (Colors = {}));

生成されたコードはパフォーマンス上の理由から問題となることもある。

実行時にenumの値が変更可能である:

TypeScriptのenumは実行時にJavaScriptオブジェクトとして存在する。これは、enumの値がランタイムで変更可能であることを意味する。

enum Colors {
  Red,
  Green,
  Blue
}

Colors.Red = 10;  // これが可能。

これはenumがconstであるべきであるという考え方とは対照的。
これらの問題を避けるためには、TypeScriptのas const構文を使用して、readonlyなオブジェクトを作成する方法が推奨される。

as const構文を使用してreadonlyな定数を作成する

これは"const assertions"と呼ばれ、TypeScript 3.4以降で利用可能。

const Directions = {
  Up: "UP",
  Down: "DOWN",
  Left: "LEFT",
  Right: "RIGHT"
} as const;

この場合、Directionsは変更不可能(readonly)であり、そのプロパティはそれぞれ文字列リテラル型("UP"、"DOWN"、"LEFT"、"RIGHT")を持つ。これにより、enumと同じように関連する定数をまとめることができ、さらにenumの持つ問題を避けることが可能になる。


参照:
列挙型(enum)の問題点と代替手段 | TypeScript入門『サバイバルTypeScript』