詳解 TypeScript 枚舉類型
前言:
TypeScript
在 ES 原有類型基礎(chǔ)上加入枚舉類型,使得在 TypeScript
中也可以給一組數(shù)值賦予名字,這樣對開發(fā)者比較友好,可以理解枚舉就是一個(gè)字典。
枚舉類型使用enum來定義:
enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY }
上面定義的枚舉類型的Day,它有7個(gè)值,TypeScript
會(huì)為它們每個(gè)值分配編號(hào),默認(rèn)從0開始,在使用時(shí),就可以使用名字而不需要記數(shù)字和名稱的對應(yīng)關(guān)系了:
enum Day { SUNDAY = 0, MONDAY = 1, TUESDAY = 2, WEDNESDAY = 3, THURSDAY = 4, FRIDAY = 5, SATURDAY = 6 }
下面是將上面代碼轉(zhuǎn)譯為 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 = {}));
可以看到,每一個(gè)值都被賦予了對應(yīng)的數(shù)字。
在TypeScript中,我們需要通過點(diǎn)的形式獲取枚舉集合中的成員:
console.log(Day.SUNDAY) // 0 console.log(Day.MONDAY) // 1
說完枚舉類型的基本使用,下面就來看一下常見的枚舉類型。
1. 數(shù)字枚舉
在上面的例子中,在僅指定常量命名的情況下,定義的就是一個(gè)默認(rèn)從 0 開始遞增的數(shù)字集合,稱之為數(shù)字枚舉。如果想要從其他值開始遞增,可以將第一個(gè)值的索引值進(jìn)行指定:
enum Color { Red = 2, Blue, Yellow } console.log(Color.Red, Color.Blue, Color.Yellow); // 2 3 4
可以對一個(gè)字段指定一個(gè)索引值,那他后面沒有指定索引值的就會(huì)依次加一:
// 指定部分字段,其他使用默認(rèn)遞增索引 enum Status { Ok = 200, Created, Accepted, BadRequest = 400, Unauthorized } console.log(Status.Created, Status.Accepted, Status.Unauthorized); // 201 202 401
除此之外,還可以給每個(gè)字段指定不連續(xù)的任意索引值:
enum Status { Success = 200, NotFound = 404, Error = 500 } console.log(Status.Success, Status.NotFound, Status.Error); // 200 404 500
數(shù)字枚舉在定義值時(shí),可以使用計(jì)算值和常量。但是要注意,如果某個(gè)字段使用了計(jì)算值或常量,那么該字段后面緊接著的字段必須設(shè)置初始值,這里不能使用默認(rèn)的遞增值了,來看例子:
// 初值為計(jì)算值 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 }
2. 字符串枚舉
TypeScript
將定義值是字符串字面量的枚舉稱為字符串枚舉,字符串枚舉值要求每個(gè)字段的值都必須是字符串字面量,或者是該枚舉值中另一個(gè)字符串枚舉成員:
// 使用字符串字面量 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'
注意:這里的其他枚舉成員指的是同一個(gè)枚舉值中的枚舉成員,因?yàn)樽址杜e不能使用常量或者計(jì)算值,所以不能使用其他枚舉值中的成員。
3. 反向映射
定義枚舉類型的值時(shí),可以通過 Enum['key']
或者 Enum.key
的形式獲取到對應(yīng)的值 value
。TypeScript
還支持反向映射,但是反向映射只支持?jǐn)?shù)字枚舉,不支持字符串枚舉。
來看下面的例子:
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
中定義的枚舉,編譯之后其實(shí)是一個(gè)對象,生成的代碼中,枚舉類型被編譯成一個(gè)對象,它包含了正向映射( name -> value)和反向映射( value -> name)。
下面來看看上面代碼中的 Status
編譯后的效果:
{ 200: "Success", 404: "NotFound", 500: "Error", Error: 500, NotFound: 404, Success: 200 }
可以看到,TypeScript
會(huì)把定義的枚舉值的字段名分別作為對象的屬性名和屬性值,把枚舉值的字段值分別作為對象的屬性值和屬性名,同時(shí)添加到對象中。這樣既可以通過枚舉值的字段名得到值,也可以通過枚舉值的值得到字段名。
4. 異構(gòu)枚舉
異構(gòu)枚舉就是枚舉值中成員值既有數(shù)字類型又有字符串類型,如下:
enum Result { Faild = 0, Success = "Success" }
在開發(fā)過程中不建議使用異步枚舉。因?yàn)橥鶎⒁活愔嫡頌橐粋€(gè)枚舉值時(shí),它們的特點(diǎn)是相似的。比如在做接口請求時(shí)的返回狀態(tài)碼,如果是狀態(tài)碼都是數(shù)值,如果是提示信息,都是字符串,所以在使用枚舉的時(shí)候,往往是可以避免使用異構(gòu)枚舉的,主要是做好類型的整理。
5. 常量枚舉
在TypeScript
中,定義了枚舉值之后,編譯成 JavaScript
的代碼會(huì)創(chuàng)建一個(gè)對應(yīng)的對象,這個(gè)對象可以在程序運(yùn)行時(shí)使用。但是如果使用枚舉只是為了讓程序可讀性好,并不需要編譯后的對象呢?這樣會(huì)增加一些編譯后的代碼量。TypeScript
中有一個(gè)const enum
(常量枚舉),在定義枚舉的語句之前加上const
關(guān)鍵字,這樣編譯后的代碼不會(huì)創(chuàng)建這個(gè)對象,只是會(huì)從枚舉里拿到相應(yīng)的值進(jìn)行替換:
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
的處理,先是定義一個(gè)變量 Status,然后定義一個(gè)立即執(zhí)行函數(shù),在函數(shù)內(nèi)給 Status
添加對應(yīng)屬性,首先Status[“Off”] = 0
是給Status
對象設(shè)置Off屬性,并且值設(shè)為 0,這個(gè)賦值表達(dá)式的返回值是等號(hào)右邊的值,也就是 0,所以Status[Status[“Off”] = 0] = "Off"
相當(dāng)于Status[0] = “Off”
。創(chuàng)建了這個(gè)對象之后,將 Status 的 On 屬性值賦值給 status;再來看下 animal 的處理,編譯后的代碼并沒有像Status創(chuàng)建一個(gè)Animal對象,而是直接把Animal.Dog
的值0替換到了const animal = Animal.Dog
表達(dá)式的Animal.Dog位置。
通過定義常量枚舉,可以以清晰、結(jié)構(gòu)化的形式維護(hù)相關(guān)聯(lián)的常量集合。而且因?yàn)檗D(zhuǎn)譯后抹除了定義、內(nèi)聯(lián)成員值,所以在代碼的體積和性能方面并不會(huì)比直接內(nèi)聯(lián)常量值差。
6. 枚舉成員類型和聯(lián)合枚舉類型
如果枚舉值里所有成員都是字面量類型的值,那么枚舉的每個(gè)成員和枚舉值本身都可以作為類型來使用,我們稱這樣的枚舉成員為字面量枚舉成員。
滿足條件的枚舉成員的值有以下三種:
- 沒有初始值的枚舉成員,例如:
enum E { A }
- 值為字符串字面量,例如:
enum E { A = 'a' }
- 值為數(shù)值字面量,或者帶有-符號(hào)的數(shù)值字面量,例如:
enum E { A = 1 }、enum E { A = -1 }
(1)枚舉成員類型
當(dāng)所有枚舉成員都擁有字面量枚舉值時(shí),就枚舉成員成為了類型:
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
的必須有一個(gè)type字段,且類型為Animal.Dog
。
(2)聯(lián)合枚舉類型
當(dāng)枚舉值符合條件時(shí),這個(gè)枚舉值就可以看做是一個(gè)包含所有成員的聯(lián)合類型:
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
,那么此時(shí) status
的屬性值必須為 Status.Off
和 Status.On 中的一個(gè),也就是相當(dāng)于status: Status.Off | Status.On
。
7. 枚舉合并
說完常見的枚舉類型,最后來看看枚舉合并的概念。對于枚舉類型的值,我們可以分開進(jìn)行聲明:
enum Day { SUNDAY, MONDAY, TUESDAY } enum Day { WEDNESDAY, THURSDAY, FRIDAY, SATURDAY }
這時(shí) TypeScript
就會(huì)對這個(gè)枚舉值進(jìn)行合并操作,合并后編譯為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 = {}));
到此這篇關(guān)于詳解 TypeScript 枚舉類型的文章就介紹到這了,更多相關(guān)TypeScript
枚舉類型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript監(jiān)測數(shù)據(jù)類型方法全面總結(jié)
這篇文章主要為大家介紹了JavaScript監(jiān)測數(shù)據(jù)類型方法示例全面總結(jié),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08JavaScript parseInt0.0000005打印5原理解析
這篇文章主要為大家介紹了JavaScript parseInt0.0000005打印5原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07JS實(shí)現(xiàn)可恢復(fù)的文件上傳示例詳解
這篇文章主要為大家介紹了JS實(shí)現(xiàn)可恢復(fù)的文件上傳示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12TypeScript新語法之infer?extends示例詳解
這篇文章主要為大家介紹了TypeScript新語法之infer?extends示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08