TypeScript Enum 逆引き 解説
TypeScript の Enum は、数値や文字列の値と関連付けられた名前の集まりです。通常、Enum の名前からその値を取得することは簡単ですが、値から名前を取得する (逆引き) には少し工夫が必要です。
なぜ逆引きが必要なのか?
- エラーハンドリング
不正な値が入力された場合、Enum の定義に基づいて適切なエラーメッセージを表示するために逆引きが役立ちます。 - 文字列ベースの Enum
文字列ベースの Enum では、値が動的に生成される場合や、外部から入力された文字列を Enum の値と照合したい場合に逆引きが必要になります。
逆引きの実装方法
手動によるループ
最もシンプルな方法は、Enum のキーをループして、対応する値と比較する方法です:
enum Direction {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}
function getDirectionKeyByValue(value: string): string | undefined {
for (const key in Direction) {
if (Direction[key] === value) {
return key;
}
}
return undefined;
}
const directionKey = getDirectionKeyByValue('DOWN'); // 'Down'
Object.keys と Object.values を利用した方法
より簡潔な方法として、Object.keys
と Object.values
を組み合わせて、Enum をオブジェクトとして扱い、値からキーを検索できます:
const directionKeys = Object.keys(Direction);
const directionValues = Object.values(Direction);
function getDirectionKeyByValue(value: string): string | undefined {
const index = directionValues.indexOf(value);
return index !== -1 ? directionKeys[index] : undefined;
}
TypeScript 4.1 以降のテンプレート文字列を利用した方法
TypeScript 4.1 以降では、テンプレート文字列を使って、より簡潔に逆引きを実現できます:
const directionKey = Object.keys(Direction)[Object.values(Direction).indexOf('DOWN')];
注意
- Enum の値が重複している場合、逆引きは正確な結果を返さない可能性があります。
- 逆引きは、Enum の定義が変更された場合に影響を受ける可能性があります。
enum Direction {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}
function getDirectionKeyByValue(value: string): string | undefined {
for (const key in Direction) {
if (Direction[key] === value) {
return key;
}
}
return undefined;
}
const directionKey = getDirectionKeyByValue('DOWN'); // 'Down'
const directionKeys = Object.keys(Direction);
const directionValues = Object.values(Direction);
function getDirectionKeyByValue(value: string): string | undefined {
const index = directionValues.indexOf(value);
return index !== -1 ? directionKeys[index] : undefined;
}
const directionKey = Object.keys(Direction)[Object.values(Direction).indexOf('DOWN')];
Enum の定義時に Map オブジェクトを使用して、値とキーの対応関係を事前に定義しておくことができます。
enum Direction {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}
const directionMap = new Map<string, string>([
[Direction.Up, 'Up'],
[Direction.Down, 'Down'],
[Direction.Left, 'Left'],
[Direction.Right, 'Right'],
]);
function getDirectionKeyByValue(value: string): string | undefined {
return directionMap.get(value);
}
const directionKey = getDirectionKeyByValue('DOWN'); // 'Down'
型ガードと条件付き型を利用する方法
TypeScript 4.1 以降では、型ガードと条件付き型を使って、より型安全な逆引きを行うことができます。
enum Direction {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}
type DirectionKey = keyof typeof Direction;
function getDirectionKeyByValue(value: string): DirectionKey | undefined {
if (value === Direction.Up) {
return 'Up';
} else if (value === Direction.Down) {
return 'Down';
} else if (value === Direction.Left) {
return 'Left';
} else if (value === Direction.Right) {
return 'Right';
}
return undefined;
}
const directionKey = getDirectionKeyByValue('DOWN'); // 'Down'
- 型ガードと条件付き型を利用する方法では、Enum の値が増えるごとにコードが冗長になる可能性があります。
- Map オブジェクトを利用する方法では、Enum の定義と Map の定義を同期させる必要があります。
typescript