關於typescript中的枚舉你需要知道這些


數字枚舉

數字枚舉,即枚舉里所有屬性的值都是數字類型,先看這段代碼:

enum Colors {
  Red,
  Blue,
  Yellow
}

console.log(Colors.Red) // 0
console.log(Colors.Blue) // 1
console.log(Colors.Yellow) // 2

 

之前也提到過,當枚舉里的屬性沒指定具體值時,默認值是從 0 開始依次排列,你也可以自己指定具體值,剩下的也是依次遞增:

enum Colors {
  Red,
  Blue = 5,
  Yellow
}

console.log(Colors.Red) // 0
console.log(Colors.Blue) // 5
console.log(Colors.Yellow) // 6

 

另外,數字枚舉在定義值的時候,可以是 常量 或者是 計算出來的。當滿足以下條件時,枚舉成員可以看作常量:

1. 它是枚舉的第一個成員且沒有初始化,這種情況下它被賦予值 0。

enum Colors {
  Red
}

 

2. 它未初始化器且它之前的枚舉成員是一個 數字常量。 這種情況下,當前枚舉成員的值為它上一個枚舉成員的值加1。

enum List1 { X, Y, Z }

enum List2 { A = 1, B, C }

// List1中沒初始化,X滿足第一個條件,是常量 0,Y 和 Z 沒初始化且之前的成員是 數字常量,所以List1所有成員都是常量

// List2 中A直接指定為常量 1,B,C 遞增為2,3,List2中也都是常量

 

3. 枚舉成員使用 常量枚舉表達式初始化。當一個表達式滿足下面條件之一時,它就是一個常量枚舉表達式:

  • 一個枚舉表達式字面量(主要是字符串字面量或數字字面量)
  • 一個對之前定義的常量枚舉成員的引用(可以是在不同的枚舉類型中定義的)
  • 帶括號的常量枚舉表達式
  • 一元運算符 +-~其中之一應用在了常量枚舉表達式
  • 常量枚舉表達式做為二元運算符 +-*/%<<>>>>>&|^的操作對象。 若常數枚舉表達式求值后為 NaN或 Infinity,則會在編譯階段報錯。

 

所有其它情況的枚舉成員被當作是需要計算得出的值。例如:

const getValue = () => {
  return 0
}

enum List {
  A = getValue(),
  B = 2,  // 此處必須要初始化值,不然編譯不通過
  C
}

console.log(List.A) // 0
console.log(List.B) // 2
console.log(List.C) // 3

A的值是被計算出來的。注意注釋部分,如果某個屬性的值是計算出來的,那么它后面一位的成員必須要初始化值。

 

反向映射

我們可以通過 Enum[key] 或者 Enum.key 的方式獲取到對應的值。typescript 還支持反向映射,即可以通過值來獲取鍵,不過反向映射只支持數字枚舉。下面是個例子:

enum Status {
  Success = 200,
  NotFound = 404,
  Error = 500
}

console.log(Status.Success) // 200
console.log(Status[200]) // Success
console.log(Status[Status.Success]) // Success

 

字符串枚舉

字符串枚舉值要求每個字段的值都必須是字符串字面量,或者是另外一個字符串枚舉成員,如下:

enum Str {
  Str1 = 'this is string one',
  Str2 = 'this is string two',
  Str3 = Str1  // 這里引用了Str1的值
}

console.log(Str.Str1) // this is string one
console.log(Str.Str2) // this is string two
console.log(Str.Str3) // this is string one

 

異構枚舉

異構枚舉是指,枚舉可以混合字符串和數字成員,如:

enum Enum {
  A = 0,
  B = 'hello'
}

console.log(Enum.A) // 0
console.log(Enum.B) // hello

這種混合值類型的枚舉通常是不需要的,不建議使用。因為往往我們將一類值整理為一個枚舉時,它們的特點都是相似的。比如我們在做接口請求時的返回狀態碼,如果是狀態碼都是數值,如果是提示信息,都是字符串。

 

枚舉成員類型和聯合枚舉類型

如果一個枚舉里所有成員的值都是字面量類型的值,那么這個枚舉的每個成員和枚舉本身都可以作為類型來使用。字面量枚舉成員需滿足以下條件:

  • 不帶初始值的枚舉成員,例如 enum E { A }
  • 值為字符串字面量,例如 enum E { A = 'hello' }
  • 值為數字字面量,或者帶有一元 符號的數字字面量,例如 enum E { A = 1 },enum E { A = -1 }

 

(1)枚舉成員類型

把符合條件的枚舉成員作為類型來使用,例子:

enum ShapeKind {
  Circle,
  Square
}

interface Circle {
  kind: ShapeKind.Circle // 使用 ShapeKind.Circle 作為類型,指定接口須有 kind 字段,且類型為 ShapeKind.Circle
  radius: number
}

interface Square {
  kind: ShapeKind.Square // 同上
  sideLength: number
}

let c: Circle = {
  kind: ShapeKind.Square, // Error! 因為接口 Circle 的 kind 被指定為 ShapeKind.Circle類型,所以這里會報錯
  radius: 100
}

interface是定義接口,現在簡單了解即可。

 

(2)聯合枚舉類型

符合條件的枚舉本身可以看作是一個包含所有成員的聯合類型,下面例子:

// 枚舉 Status 里有兩個狀態
enum Status {
  Off,
  On
}

// 枚舉 Animal 里有兩個動物
enum Animal {
  Cat,
  Dog
}

// 接口 Light 中定義 status字段,它是 Status 類型,可以是 Off 或者 On 狀態
interface Light {
  status: Status
}

let lg1: Light = {
  status: Status.Off // 正確
}

let lg2: Light = {
  status: Animal.Cat // error 不能將類型 Animal.Cat 分配給類型 Status
}

 

運行時的枚舉

枚舉是在運行時真正存在的對象,可以把枚舉當作對象使用:

enum E {
  A,
  B
}

function func(obj: { A: number }): number {
  return obj.A
}

console.log(func(E)) // 0

代碼中,聲明了一個函數 func,它的參數是一個對象,且必須包含屬性名為 A 的屬性,A 的值為數值類型。當調用函數 func 時,把枚舉 E 當作符合條件的實參傳入,正確運行。

 

const enum

定義的枚舉,在經過編譯器編譯后是一個對象,這個對象我們可以在程序運行時使用,前面有說到。但有時定義枚舉可能只是為了讓程序可讀性更好,而不需要編譯后的代碼,即不需要編譯成對象。typescript中考慮到這種情況,所以加入了 const enum (完全嵌入的枚舉)。typescript官網有一個在線編譯器,來看看下面的例子:

enum Status{
    Off,
    On
}

const enum Animal{
    Dog,
    Cat
}

const status = Status.On
const animal = Animal.Dog

這段代碼編譯成JavaScript后是這樣的:

var Status;
(function (Status) {
    Status[Status["Off"] = 0] = "Off";
    Status[Status["On"] = 1] = "On";
})(Status || (Status = {}));
var status = Status.On;
var animal = 0 /* Dog */;

可以看到編譯后的代碼中並沒有像創建Status一樣創建了Animal,而是直接把 Animal 中 Dog 值 0 替換到表達式中 Animal.Dog 的位置,這樣就節省了生成代碼的開銷。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM