
TypeScriptでenumを使ってはいけない主な3つの理由
1. 存在しない場合でも警告が出ない
TypeScript
enum Mode {
Auto,
UDP,
TCP,
}
console.log(Mode[0]) // "Auto"
console.log(Mode[4]) // undefined(警告が出ない)
2. コンパイル後の構造が複雑化する
TypeScript
enum Mode {
Auto,
UDP,
TCP,
}
// コンパイル後は以下のコードになる
{
0: "Auto",
1: "UDP",
2: "TCP",
Auto: 0,
UDP: 1,
TCP: 2
}
3. 予期せぬ型の混合アクセスが可能
TypeScript
// コンパイル後のコードが前述のようになっているため以下の結果になる
console.log(Mode.Auto) // 0
console.log(Mode['Auto']) // 0
console.log(Mode[0]) // Auto
enumの代替案
オブジェクトで生成する(キーと値が異なる場合)
TypeScript
const Mode = {
Auto: 'Auto1',
UDP: 'UDP2',
TCP: 'TCP3',
} as const satisfies Record<string, string>
console.log(Mode.UDP)
// UDP2
console.log(Mode[0])
// undefined(警告が出る)
console.log(Object.values(Mode).at(0))
// Auto1
console.log(Object.values(Mode).at(-1))
// TCP3
オブジェクトを関数で生成する(キーと値が同じ場合)
TypeScript
function createEnum<T extends readonly string[]>(keys: T) {
return Object.fromEntries(keys.map(k => [k, k])) as { [K in T[number]]: K }
}
const Mode = createEnum(['Auto', 'UDP', 'TCP'] as const)
type Mode = typeof Mode[keyof typeof Mode]
console.log(Mode.UDP)
// UDP
console.log(Mode[0])
// undefined(警告が出る)
console.log(Object.values(Mode).at(0))
// Auto
console.log(Object.values(Mode).at(-1))
// TCP