【JavaScript】Symbolを駆使してenumぽいものを定義する
概要
JavaScriptでsymbol型を使う事によって、enumっぽいものの実装ができます。 そこそここなれてきたので紹介します。
前説
JavaScriptでenumを作るパターン
JavaScriptではenumが基本無いので、あの手この手でenumっぽいものを作る必要があります。
単純にconstで定義するパターン
こういうの
const ENUM = { HOGE: "hoge", FUGA: "fuga, } function isHoge(enum) { return enum === ENUM.HOGE); }
enumクラスを自作
他にもあると思います。
何が不満?
enumっぽいけど実体はただのObjectなので、enumを使わないでサボった実装でも動いてしまいます。
const ENUM = { HOGE: "hoge", FUGA: "fuga, } function isHoge(enum) { return enum === ENUM.HOGE); } // 想定された使われ方 isHoge(ENUM.HOGE); // true // さぼった使われ方 isHoge("hoge"); // true
Symbol(シンボル)とは
まあ今回のネタはほとんどこちらに書いてあるのですが、ポイントは
console.log(Symbol("Hoge") === Symbol("Hoge")); // false
という事です。RubyのSymbolとはだいぶイメージが違うので気をつけましょう。
実装
const ENUM = { HOGE: Symbol("hoge"), FUGA: Symbol("fuga), } function isHoge(enum) { return enum === ENUM.HOGE); } // 想定された使われ方 isHoge(ENUM.HOGE); // true // さぼった使われ方 isHoge("hoge"); // false isHoge(Symbol("hoge")); // false
はい、これでENUM
を使うことを強制できました。
jsonにしたり、シリアライズしてDBに保存したりしたい時は、
enumKeyString(enum) { switch (enum) { case ENUM.HOGE: return "hoge"; case ENUM.FUGA: return "fuga"; ] }
とか
const ENUM_KEY_STRING = { [ENUM.HOGE]: "hoge", [ENUM.FUGA]: "fuga", }
とかを用意してSymbolじゃない型でシリアライズしてあげるくらいしか手がありません。 ださいしめんどくさい、、、
※Symbol("hoge")
の hoge
はdescriptionなので、ロジックには使いたく無い。toStringしてもSymbol(hoge)
になる、、、微妙、、
※typescriptを使えばいいじゃん、とか言わない事