1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

enumがなにかわからなかったから調べた話

Last updated at Posted at 2024-12-19

私が最初に触れたプログラミング言語はNode.jsでした
御存知の通りNode.jsにはenumに相当する機能がないんです
なのでenumについて知らずに、必要性も感じずに生きてきました
実はTypeScriptの方針に反するものなのですが、TypeScriptの中にenumが存在します

ふとした時に疑問に持ち、色々と調べたので自分なりに、特にNode.js、TypeScriptについて書き残しておきます

enumとは

enumとは列挙型のことで英語だとenumerated typeと呼ぶようです
おそらく英語の頭をとってenumと読んでいるのでしょう

これは定数のリストをコンパクトに纏めるためのものみたいです
宣言時に明示的に指定しなければ0から順番に連番が当てられるようです
また宣言時に変数を用いて指定することもできDATEを現在時刻のUnix時間になるようにしています
他にも、他言語では明示的なキャストなしにはできないものもあるようですが、TypeScriptではenumを算術計算に直接使えるようです

それと最後//@ts-expect-errorでエラーが出ることを許容しています
後で説明していますがこれによってenumの定数を扱うという特性が破壊されています

TypeScript
const date = new Date().getTime();

enum testEnum {
  AAAAA,      // 0
  BBBBB,      // 1
  CCCCC,      // 2
  EEEEE = 5,  // 明示的に5になる
  DATE = date // Unix時間になる
}

/* 
  という形で宣言し
  以下のように使用する
*/

console.log(testEnum.AAAAA)      // 0

const testVar1 = testEnum.BBBBB
console.log(testVar1)             // 1

let testVar2 = testEnum.CCCCC
testVar2 += 10
console.log(testVar2)            // 12

console.log(testEnum.EEEEE)      // 5

console.log(testEnum.DATE)       // new Date()時点でのunix時間

testEnum.AAAAA = 10 //これはエラー

//@ts-expect-error
testEnum.AAAAA = 10               //型チェックを無視すると代入できてしまう
console.log(testEnum.AAAAA)      // 10

トランスパイル後

トランスパイル後コードはこの様になっています
少し見やすいように整形を入れています

Node.js
const date = new Date().getTime();

// ここから
var testEnum;
(function (testEnum) {
    testEnum[testEnum["AAAAA"] = 0] = "AAAAA";
    testEnum[testEnum["BBBBB"] = 1] = "BBBBB";
    testEnum[testEnum["CCCCC"] = 2] = "CCCCC";
    testEnum[testEnum["EEEEE"] = 5] = "EEEEE";
    testEnum[testEnum["DATE"] = date] = "DATE"; // Unix時間になる
})(testEnum || (testEnum = {}));
// ここまで

console.log(testEnum.AAAAA); // 0

const testVar1 = testEnum.BBBBB;
console.log(testVar1); // 1

let testVar2 = testEnum.CCCCC;
testVar2 += 10;
console.log(testVar2); // 12

console.log(testEnum.EEEEE); // 5

console.log(testEnum.DATE); // new Date()時点でのunix時間

//testEnum.AAAAA = 10 // これはエラー

//@ts-expect-error
testEnum.AAAAA = 10; // 型チェックを無視すると代入できてしまう
console.log(testEnum.AAAAA); // 10

enumがなにか違う構造に変換されているのがわかりますね
これに関しては正直何してるかわかりません
// TODO またいつか勉強する const enumの記事で触れています

それと//@ts-expect-errorを指定してtestEnum.AAAAA = 10の型のエラーを無視しています
トランスパイル後にもコードが残ってしまっていますね

実行

console
0
1
12
5
1734527678178
10

実行結果でも上の結果が出ていることがわかります
特に最後の10、型安全性を破壊した結果enumの定数を扱うという性質を破壊できてしまいました
やはりAnyは敵ですね

普通に使う分には//@ts-expect-errorなんて使わないと思うのでAnyなどに気をつけていれば問題ないと思います
それ以外にもいくつかコンパイラを騙して型安全性を破壊できてしまうアンチパターンが存在しているので、気を付けてコーディングしていきましょう

今日も ご安全に 型安全に

まとめ

  • 名前付き定数をまとめて宣言
  • enum.<定数名>の形で使用
  • 値はnumber型として使用できる == 算術計算に使える
  • 生JSには存在せず同等の機能にトランスパイルされる
  • TypeScriptの型安全性に守られているだけであり、型チェックを無効化すると改変できてしまう
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?