TypeScriptのEnum(列挙型)にはvalueOf(文字列から対応するenum要素を取得する)メソッドが用意されていないため、実装を追加する方法を調査した。なお、Enumには任意のメソッドを追加できないため、namespaceを利用して実装している。
Numeric Enum
自動インクリメントされた数値が割り当てられる数値型(Numeric)Enumでは、逆引きマップ(Reverse Mapping)が利用できるため、Enum[string]
でvalueOf相当の処理を実現できる。ただし、そのままでは型エラー(Element implicitly has an 'any' type...)となるため、以下のいずれかの記述とする必要がある。
Enum[string as keyof typeof Enum]
(<any>Enum)[string]
実装例
/* Numeric Enum */
enum Color { Red, Green };
// toString()
Color.Green.toString(); // => '1'
Color[Color.Green]; // => 'Green'
// valueOf()
namespace Color {
export function valueOf(str: string) {
return Color[str as keyof typeof Color];
}
}
const str = 'Green';
Color.valueOf(str); // => NumericEnum.Green
String Enum
任意の文字列を割り当てる文字列型(String)Enumでは、Reverse Mappingが利用できない(※)ため、自分で逆引き用のMapオブジェクトを用意する必要がある。
実装例
/* String Enum */
enum Color { Red = 'red', Green = 'green' };
// toString()
Color.Green.toString(); // => 'green'
// valueOf()
namespace Color {
const reverseMap = new Map<string, Color>();
Object.keys(Color).forEach((s: string) => {
const e = (<any>Color)[s];
reverseMap.set(e.toString(), e);
});
export function valueOf(str: string) {
return reverseMap.get(str);
}
}
const str = 'green';
Color.valueOf(str); // => StringEnum.Green
※ Numeric Enumと同様にEnumのキー名からEnumを取得することはできるが、Enumに割り当てた文字列からEnumを取得することはできない。
let str = 'Green'
Color[str as keyof typeof Color]; // => Color.Green
str = 'green'
Color[str as keyof typeof Color]; // => undefined