0%

重新學習TS-三-TypeScript-enum 列舉類型

前言

深入研究 ENUM 類型


Enum 是 TS 增加的新語法,也被稱做「列舉」或「列舉

列舉是一個被命名的整型常數的集合,用於聲明一組命名的常數,
當一個變量有幾種可能的取值時,
可以將它定義為列舉類型

通俗來說,列舉就是一個對象的所有可能取值的集合
可以想成就是將東西一個一個列出來,通常會用它來管理多個同系列的常數(不可修改的變數),將常數值一一列舉出來,且只能在列舉出來的範圍中選擇

在日常生活中也很常見,
例如表示星期的SUNDAYMONDAYTUESDAYWEDNESDAYTHURSDAYFRIDAYSATURDAY就可以看成是一個列舉
或是 交通號誌顏色的列舉,元素就是是三個。

列舉的說明結構和聯合相似,其形式為:

1
2
3
4
5
6
enum 列舉名稱{
標示符號 ① [=整型常數],
標示符號 ② [=整型常數],
...
標示符號 N [=整型常數],
}列舉變量;

列舉又分三種型別,分別為

  • 數字列舉(Number enum)
  • 字串列舉(String enum)
  • 異構列舉(Heterogeneous enum)

使用方式

列舉的使用是通過enum關鍵字進行定義,形式如下:

1
enum xxx { ... }

聲明關鍵字為列舉類型的方式如下:

1
2
3
// 聲明d為列舉類型Direction
let d: Direction;

數字列舉

當我們聲明一個列舉類型,雖然沒有給它們賦值,
但是它們的值其實是默認的數字類型,而且默認從0開始依次累加:

1
2
3
4
5
6
7
8
9
10
11
enum Direction {
Up, // 值默認為 0
Down, // 值默認為 1
Left, // 值默認為 2
Right // 值默認為 3
}

console.log(Direction.Up === 0); // true
console.log(Direction.Down === 1); // true
console.log(Direction.Left === 2); // true
console.log(Direction.Right === 3); // true

如果我們將第一個值進行賦值後,後面的值也會根據前一個值進行累加 1 :

1
2
3
4
5
6
7
8
enum Direction {
Up = 10,
Down,
Left,
Right
}

console.log(Direction.Up, Direction.Down, Direction.Left, Direction.Right); // 10 11 12 13

字串列舉

1
2
3
4
5
6
7
8
9
10
列舉類型的值其實也可以是字串類型:

enum Direction {
Up = 'Up',
Down = 'Down',
Left = 'Left',
Right = 'Right'
}

console.log(Direction['Right'], Direction.Up); // Right Up

如果設定了一個變量為字符串之後,後續的字段也需要賦值字符串,否則報錯:

1
2
3
4
5
6
enum Direction {
Up = 'UP',
Down, // error TS1061: Enum member must have initializer
Left, // error TS1061: Enum member must have initializer
Right // error TS1061: Enum member must have initializer
}

異構列舉

即將數字列舉字串列舉結合起來混合起來使用,如下:

1
2
3
4
enum BooleanLikeHeterogeneousEnum {
No = 0,
Yes = "YES",
}

通常情況下我們很少會使用異構列舉

本質

現在一個列舉的案例如下:

1
2
3
4
5
6
enum Direction {
Up,
Down,
Left,
Right
}

通過編譯後 JavaScript代碼如下

1
2
3
4
5
6
7
var Direction;
(function (Direction) {
Direction[Direction["Up"] = 0] = "Up";
Direction[Direction["Down"] = 1] = "Down";
Direction[Direction["Left"] = 2] = "Left";
Direction[Direction["Right"] = 3] = "Right";
})(Direction || (Direction = {}));

上述代碼可以看到,Direction[Direction["Up"] = 0] = "Up" 可以分成

Direction[0] = "Up"
Direction["Up"] = 0

所以定義列舉類型後,可以通過正反映射拿到對應的值,如下:

1
2
3
4
5
6
7
8
9
enum Direction {
Up,
Down,
Left,
Right
}

console.log(Direction.Up === 0); // true
console.log(Direction[0]); // Up

並且多處定義的列舉是可以進行合併操作,如下:

1
2
3
4
5
6
7
8
9
10
enum Direction {
Up = 'Up',
Down = 'Down',
Left = 'Left',
Right = 'Right'
}

enum Direction {
Center = 1
}

編譯後,js代碼如下:

1
2
3
4
5
6
7
8
9
10
var Direction;
(function (Direction) {
Direction["Up"] = "Up";
Direction["Down"] = "Down";
Direction["Left"] = "Left";
Direction["Right"] = "Right";
})(Direction || (Direction = {}));
(function (Direction) {
Direction[Direction["Center"] = 1] = "Center";
})(Direction || (Direction = {}));

可以看到,Direction對象屬性回疊加

了解這些特性之後 來個實際例子

舉個例子

拿大家最常使用的星期來當例子

後端返回的字段使用0 - 6 標記對應的日期,這時候就可以使用列舉可提高代碼可讀性,如下:

1
2
3
4
5
6
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};

console.log(Days["Sun"] === 0); // true
console.log(Days["Mon"] === 1); // true
console.log(Days["Tue"] === 2); // true
console.log(Days["Sat"] === 6); // true

包括後端日常返回0、1 等等狀態的時候,我們都可以通過列舉去定義,這樣可以提高代碼的可讀性,便於後續的維護


References

你的支持是我活力的來源 :)