TypeScriptのEnumの何がダメなのか
TypeScriptのEnum使うのは避けようという事を耳にしたのできちんと調べた
自分なりに脱却案を記した
数値型Enum
enum.ts
enum Sex {
male,
female
}
console.log(Sex.male) //0
console.log(Sex[0]) //male
数値は自由に選択可能
enum.ts
enum Sex {
male = 1,
female
}
console.log(Sex.male) //1
console.log(Sex.female) //2
console.log(Sex[1]) //male
問題点
コンパイルエラーにならないので気づかずに999を代入できてしまう。むかつく。
enum.ts
enum Sex {
male = 1,
female
}
const hoge: Sex = 999 //コンパイルエラーにならない
console.log(hoge) //999
console.log(Sex[hoge]) //undifined
EnumはTypeScriptの独自機能なのでコンパイルされるとこうなる
enum.js
var Sex;
(function (Sex) {
Sex[Sex["male"] = 1] = "male";
Sex[Sex["female"] = 2] = "female";
})(Sex || (Sex = {}));
文字列型のEnum
文字列を指定することができる。文字列での代入ができないので変更があった場合に最小限で済む。
enum.ts
enum Sex {
male = "男性",
female = "女性"
}
const hoge: Sex = Sex.male
const fuga: Sex = "男性" //コンパイルエラー
console.log(hoge) //男性
console.log(Sex["male"]) //男性
以下でもできる。コンパイル結果は変わらないのでキーが文字列で記述することが明示的なことから個人的にはこちらが良い気がしてる
Enumを使うとするならばですが。。。
enum.ts
enum Sex {
"male" = "男性",
"female" = "女性"
}
console.log(Sex["male"]) //男性
enum.ts
var Sex;
(function (Sex) {
Sex["male"] = "\u7537\u6027";
Sex["female"] = "\u5973\u6027";
})(Sex || (Sex = {}));
const Enum
enum.ts
const enum Sex {
male = 1,
female
}
const hoge: Sex = Sex.male
constを入れることによって使用時にインライン化してコンパイルされる。
enum.ts
const hoge = 1 /* male */;
Enumがダメなところ
全般
- 数値型Enumが型安全でない
- 上記で示した通り
constでないEnum
constでないEnumの欠点は2つ
- そもそもTypeScriptの概念に合っていない
- TypeScriptはJavaScriptとの互換性があり静的型付けができることがコンセプトなのに互換性がない
- Tree-shakingできない
- コンパイル時に即時関数を作り出すので使われているかどうか判断できない
const Enum
- Babelでのトランスパイルができない
- 方法はあるがプラグインを入れたりなど手間が生じる
Enum脱却
じゃあどうするか…
コンパイル時にオブジェクトを生成するんだったら
初めからオブジェクト作ればよくないか!?ってことで以下にした
index.ts
const sexNumber = {
male: 0,
female: 1
} as const
console.log(sexNumber["male"]) //0
const sexString = {
male: "男性",
female: "女性"
} as const
console.log(sexString["male"]) //男性
脱却できたかと思う。
ご意見があればコメントお願い致します!!
参照
さようなら、TypeScript enum
TypeScriptのenumを使わないほうがいい理由を、Tree-shakingの観点で紹介します