簡單探討TypeScript 列舉型別
TypeScript 在 ES 原有型別基礎上加入列舉型別,使得在 TypeScript 中也可以給一組數值賦予名字,這樣對開發者比較友好,可以理解列舉就是一個字典。
列舉型別使用enum來定義:
enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY }
上面定義的列舉型別的Day,它有7個值,TypeScript會為它們每個值分配編號,預設從0開始,在使用時,就可以使用名字而不需要記數字和名稱的對應關係了:
enum Day { SUNDAY = 0, MONDAY = 1, TUESDAY = 2, WEDNESDAY = 3, THURSDAY = 4, FRIDAY = 5, SATURDAY = 6 }
下面是將上面程式碼轉譯為 JavaScript 後的效果:
var Day = void 0; (function (Day) { Day[Day["SUNDAY"] = 0] = "SUNDAY"; Day[Day["MONDAY"] = 1] = "MONDAY"; Day[Day["TUESDAY"] = 2] = "TUESDAY"; Day[Day["WEDNESDAY"] = 3] = "WEDNESDAY"; Day[Day["THURSDAY"] = 4] = "THURSDAY"; Day[Day["FRIDAY"] = 5] = "FRIDAY"; Day[Day["SATURDAY"] = 6] = "SATURDAY"; })(Day || (Day = {}));
可以看到,每一個值都被賦予了對應的數字。
在TypeScript中,我們需要透過點的形式獲取列舉集合中的成員:
console.log(Day.SUNDAY) // 0 console.log(Day.MONDAY) // 1
說完列舉型別的基本使用,下面就來看一下常見的列舉型別。
在上面的例子中,在僅指定常量命名的情況下,定義的就是一個預設從 0 開始遞增的數字集合,稱之為數字列舉。如果想要從其他值開始遞增,可以將第一個值的索引值進行指定:
enum Color { Red = 2, Blue, Yellow } console.log(Color.Red, Color.Blue, Color.Yellow); // 2 3 4
可以對一個欄位指定一個索引值,那他後面沒有指定索引值的就會依次加一:
// 指定部分欄位,其他使用預設遞增索引 enum Status { Ok = 200, Created, Accepted, BadRequest = 400, Unauthorized } console.log(Status.Created, Status.Accepted, Status.Unauthorized); // 201 202 401
除此之外,還可以給每個欄位指定不連續的任意索引值:
enum Status { Success = 200, NotFound = 404, Error = 500 } console.log(Status.Success, Status.NotFound, Status.Error); // 200 404 500
數字列舉在定義值時,可以使用計算值和常量。但是要注意,如果某個欄位使用了計算值或常量,那麼該欄位後面緊接著的欄位必須設定初始值,這裡不能使用預設的遞增值了,來看例子:
// 初值為計算值 const getValue = () => { return 0; }; enum ErrorIndex { a = getValue(), b, // error 列舉成員必須具有初始化的值 c } enum RightIndex { a = getValue(), b = 1, c } // 初值為常量 const Start = 1; enum Index { a = Start, b, // error 列舉成員必須具有初始化的值 c }
TypeScript 將定義值是字串字面量的列舉稱為字串列舉,字串列舉值要求每個欄位的值都必須是字串字面量,或者是該列舉值中另一個字串列舉成員:
// 使用字串字面量 enum Message { Error = "Sorry, error", Success = "Hoho, success" } console.log(Message.Error); // 'Sorry, error' // 使用列舉值中其他列舉成員 enum Message { Error = "error message", ServerError = Error, ClientError = Error } console.log(Message.Error); // 'error message' console.log(Message.ServerError); // 'error message'
注意:這裡的其他列舉成員指的是同一個列舉值中的列舉成員,因為字串列舉不能使用常量或者計算值,所以不能使用其他列舉值中的成員。
定義列舉型別的值時,可以透過 Enum['key'] 或者 Enum.key 的形式獲取到對應的值 value。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'
TypeScript 中定義的列舉,編譯之後其實是一個物件,生成的程式碼中,列舉型別被編譯成一個物件,它包含了正向對映( name -> value)和反向對映( value -> name)。
下面來看看上面程式碼中的 Status 編譯後的效果:
{ 200: "Success", 404: "NotFound", 500: "Error", Error: 500, NotFound: 404, Success: 200 }
可以看到,TypeScript 會把定義的列舉值的欄位名分別作為物件的屬性名和屬性值,把列舉值的欄位值分別作為物件的屬性值和屬性名,同時新增到物件中。這樣既可以透過列舉值的欄位名得到值,也可以透過列舉值的值得到欄位名。
異構列舉就是列舉值中成員值既有數字型別又有字串型別,如下:
enum Result { Faild = 0, Success = "Success" }
在開發過程中不建議使用非同步列舉。因為往往將一類值整理為一個列舉值時,它們的特點是相似的。比如在做介面請求時的返回狀態碼,如果是狀態碼都是數值,如果是提示資訊,都是字串,所以在使用列舉的時候,往往是可以避免使用異構列舉的,主要是做好型別的整理。
在TypeScript中,定義了列舉值之後,編譯成 JavaScript 的程式碼會建立一個對應的物件,這個物件可以在程式執行時使用。但是如果使用列舉只是為了讓程式可讀性好,並不需要編譯後的物件呢?這樣會增加一些編譯後的程式碼量。TypeScript 中有一個const enum(常量列舉),在定義列舉的語句之前加上const關鍵字,這樣編譯後的程式碼不會建立這個物件,只是會從列舉裡拿到相應的值進行替換:
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 的處理,先是定義一個變數 Status,然後定義一個立即執行函式,在函式內給 Status 新增對應屬性,首先Status[“Off”] = 0是給Status物件設定Off屬性,並且值設為 0,這個賦值表示式的返回值是等號右邊的值,也就是 0,所以Status[Status[“Off”] = 0] = "Off"相當於Status[0] = “Off” 。建立了這個物件之後,將 Status 的 On 屬性值賦值給 status;再來看下 animal 的處理,編譯後的程式碼並沒有像Status建立一個Animal物件,而是直接把Animal.Dog的值0替換到了const animal = Animal.Dog表示式的Animal.Dog位置。
透過定義常量列舉,可以以清晰、結構化的形式維護相關聯的常量集合。而且因為轉譯後抹除了定義、內聯成員值,所以在程式碼的體積和效能方面並不會比直接內聯常量值差。
如果列舉值裡所有成員都是字面量型別的值,那麼列舉的每個成員和列舉值本身都可以作為型別來使用,我們稱這樣的列舉成員為字面量列舉成員。
滿足條件的列舉成員的值有以下三種:
沒有初始值的列舉成員,例如:enum E { A }
值為字串字面量,例如:enum E { A = 'a' }
值為數值字面量,或者帶有-符號的數值字面量,例如:enum E { A = 1 }、enum E { A = -1 }
當所有列舉成員都擁有字面量列舉值時,就列舉成員成為了型別:
enum Animal { Dog = 1, Cat = 2 } interface Dog { type: Animal.Dog; } interface Cat { type: Animal.Cat; } let cat: Cat = { type: Animal.Dog // error [ts] 不能將型別“Animal.Dog”分配給型別“Animal.Cat” }; let dog: Dog = { type: Animal.Dog };
可以看到,程式碼的第七行使用Animal.Dog作為型別,指定介面Dog的必須有一個type欄位,且型別為Animal.Dog。
當列舉值符合條件時,這個列舉值就可以看做是一個包含所有成員的聯合型別:
enum Status { Off, On } interface Light { status: Status; } enum Animal { Dog = 1, Cat = 2 } const light1: Light = { status: Animal.Dog // error 不能將型別“Animal.Dog”分配給型別“Status” }; const light2: Light = { status: Status.Off }; const light3: Light = { status: Status.On };
上面例子定義介面 Light 的 status 欄位的型別為列舉值 Status,那麼此時 status 的屬性值必須為 Status.Off 和 Status.On 中的一個,也就是相當於status: Status.Off | Status.On。
說完常見的列舉型別,最後來看看列舉合併的概念。對於列舉型別的值,我們可以分開進行宣告:
enum Day { SUNDAY, MONDAY, TUESDAY } enum Day { WEDNESDAY, THURSDAY, FRIDAY, SATURDAY }
這時 TypeScript 就會對這個列舉值進行合併操作,合併後編譯為JavaScript的程式碼如下:
var Day = void 0; (function (Day) { Day[Day["SUNDAY"] = 0] = "SUNDAY"; Day[Day["MONDAY"] = 1] = "MONDAY"; Day[Day["TUESDAY"] = 2] = "TUESDAY"; Day[Day["WEDNESDAY"] = 3] = "WEDNESDAY"; Day[Day["THURSDAY"] = 4] = "THURSDAY"; Day[Day["FRIDAY"] = 5] = "FRIDAY"; Day[Day["SATURDAY"] = 6] = "SATURDAY"; })(Day || (Day = {}));
到此這篇關於詳解 TypeScript 列舉型別的文章就介紹到這了
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69901823/viewspace-2842025/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 窺探Swift之別樣的列舉型別Swift型別
- 簡單探討JavaScript 與 TypeScript之間的聯絡JavaScriptTypeScript
- TypeScript 中列舉型別的理解?應用場景?TypeScript型別
- 結構體-簡單列舉型別——植物與顏色結構體型別
- 列舉型別型別
- TypeScript 陣列型別TypeScript陣列型別
- ENUM列舉型別型別
- java列舉型別Java型別
- java 列舉型別Java型別
- TypeScript 列舉enumTypeScript
- TypeScript 列舉指南TypeScript
- Java - Enum 列舉型別Java型別
- 列舉簡單總結
- java中的列舉型別Java型別
- JavaSE基礎:列舉型別Java型別
- mysql之ENUM列舉型別MySql型別
- 【C++】資料型別-列舉型C++資料型別
- C++ 列舉型別介紹C++型別
- 列舉型別分享 第五節型別
- java基礎(十一) 列舉型別Java型別
- Python 中的列舉型別Python型別
- 列舉型別與位運算型別
- 10-列舉型別和流型別
- 關於C++列舉型別C++型別
- TypeScript 簡明教程:基本型別(二)TypeScript型別
- TypeScript 簡明教程:基本型別(一)TypeScript型別
- JPA不識別MySQL的列舉型別MySql型別
- OC中列舉寫法 以及 字串型別列舉實現探索字串型別
- NSOperation的進階使用和簡單探討
- NSThead的進階使用和簡單探討
- 聊聊TypeScript中列舉物件(Enum)TypeScript物件
- TypeScript this型別TypeScript型別
- java中的列舉型別學習Java型別
- Java基礎教程(15)–列舉型別Java型別
- C語言 列舉資料型別C語言資料型別
- 列舉型別在JPA中的使用型別
- 補充:C語言列舉型別C語言型別
- Java列舉型別的使用和原理Java型別