Day13: 【TypeScript 學起來】只有 TS 才有的型別: Enums(列舉)

是說TS針對型別的類型也太講究,寫好多天還沒寫完(其實是我30篇不夠XDD),哈哈不囉嗦, 今天繼續筆記列舉(Enums)型別。

列舉(Enums)型別用於取值被限定在一定範圍內的場景,可以用來管理多個同系列的常數,作為狀態判斷使用。比如一週只能有七天,顏色限定為紅綠藍等。也可以自定義來表示每一個值。


Numeric Enums

使用enum關鍵字來定義:

enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};

這時候我們來看編譯後,列舉成員會被賦值為從 0 開始自動遞增的數字,同時也會對列舉值到列舉名進行反向對映:

var Days;
(function (Days) {
    Days[Days["Sun"] = 0] = "Sun";
    Days[Days["Mon"] = 1] = "Mon";
    Days[Days["Tue"] = 2] = "Tue";
    Days[Days["Wed"] = 3] = "Wed";
    Days[Days["Thu"] = 4] = "Thu";
    Days[Days["Fri"] = 5] = "Fri";
    Days[Days["Sat"] = 6] = "Sat";
})(Days || (Days = {}));

手動賦值

可以手動去定義不同的值。

enum Days {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat};

編譯後:

var Days;
(function (Days) {
    Days[Days["Sun"] = 7] = "Sun";
    Days[Days["Mon"] = 1] = "Mon";
    Days[Days["Tue"] = 2] = "Tue";
    Days[Days["Wed"] = 3] = "Wed";
    Days[Days["Thu"] = 4] = "Thu";
    Days[Days["Fri"] = 5] = "Fri";
    Days[Days["Sat"] = 6] = "Sat";
})(Days || (Days = {}));

要小心覆蓋的情況

如果中間突然指定了了一個值,那他會從當前的值從新開始計算。如下, Days[3] 的值先是 "Sun",而後又被 "Wed" 覆蓋了。這個TypeScript 是不會報錯的,所以要特別注意。

enum Days {Sun = 3, Mon = 1, Tue, Wed, Thu, Fri, Sat};

console.log(Days["Sun"] === 3); // true
console.log(Days["Wed"] === 3); // true
console.log(Days[3] === "Sun"); // false
console.log(Days[3] === "Wed"); // true

可使用型別斷言(Type Assertion)來定義

手動賦值的列舉項其中一個不想是數字,此時可以使用 any 型別斷言來讓TypeScript 無視型別檢查。

enum Days {Sun = 7, Mon, Tue, Wed, Thu, Fri, Sat = <any>"S"};

編譯後:

var Days;
(function (Days) {
    Days[Days["Sun"] = 7] = "Sun";
    Days[Days["Mon"] = 8] = "Mon";
    Days[Days["Tue"] = 9] = "Tue";
    Days[Days["Wed"] = 10] = "Wed";
    Days[Days["Thu"] = 11] = "Thu";
    Days[Days["Fri"] = 12] = "Fri";
    Days[Days["Sat"] = "S"] = "Sat";
})(Days || (Days = {}));

String Enums 字串列舉

字串 enums 沒有number enums 可以自動遞增的行為, 但字串enum自行定義是有他的語意在的。

enum Direction {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT",
}

Heterogeneous Enums 異構列舉

雖然enum可以混合數字與字串,但盡量不要寫這種寫法:

enum BooleanLikeHeterogeneousEnum {
  No = 0,
  Yes = "YES",
}

Computed and constant members 常數項和計算所得項

列舉項有兩種型別:常數項(constant member)和計算所得項(computed member)。

前面我們所舉的例子都是常數項,一個典型的計算所得項的例子如下,"blue".length 就是一個計算所得項。:

enum Color {Red, Green, Blue = "blue".length};
console.log(Color.Blue); //4

如何定義是常數項,可參考 這篇官網

像是二元運算子 <<|& 等都歸為常數項:

enum FileAccess {
  // constant members
  None,
  Read = 1 << 1,
  Write = 1 << 2,
  ReadWrite = Read | Write,
  // computed member
  G = "123".length,
}

Const Enums 常數列舉

可以使用 const enum 定義的列舉型別:

const enum Directions {
    Up,
    Down,
    Left,
    Right
}

let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];

常數列舉與普通列舉的區別是,它會在編譯階段被刪除,並且不能包含computed member(計算成員), 只能是常數項(constant member)。

編譯後:

var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];

Ambient Enums 外部列舉

外部列舉(Ambient Enums)是使用 declare enum 定義的列舉型別:

declare enum Directions {
    Up,
    Down,
    Left,
    Right
}

let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];

declare 定義的型別只會用於編譯時的檢查,編譯結果中會被刪除。

編譯後:

var directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];

下一篇終於來介紹interface了!! 撒花~


參考資料

https://willh.gitbook.io/typescript-tutorial/advanced/enum#chang-shu-xiang-he-ji-suan-suo-de-xiang
https://www.typescriptlang.org/docs/handbook/enums.html

Leave a Comment

Your email address will not be published. Required fields are marked *

ZH-TW EN ES