溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何理解TypeScript枚舉類型

發(fā)布時(shí)間:2021-10-28 17:25:11 來(lái)源:億速云 閱讀:151 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本篇內(nèi)容主要講解“如何理解TypeScript枚舉類型”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“如何理解TypeScript枚舉類型”吧!

    前言:

    TypeScript 在 ES 原有類型基礎(chǔ)上加入枚舉類型,使得在 TypeScript 中也可以給一組數(shù)值賦予名字,這樣對(duì)開(kāi)發(fā)者比較友好,可以理解枚舉就是一個(gè)字典。

    枚舉類型使用enum來(lái)定義:

    enum Day {
      SUNDAY,
      MONDAY,
      TUESDAY,
      WEDNESDAY,
      THURSDAY,
      FRIDAY,
      SATURDAY
     }

    上面定義的枚舉類型的Day,它有7個(gè)值,TypeScript會(huì)為它們每個(gè)值分配編號(hào),默認(rèn)從0開(kāi)始,在使用時(shí),就可以使用名字而不需要記數(shù)字和名稱的對(duì)應(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è)值都被賦予了對(duì)應(yīng)的數(shù)字。

    在TypeScript中,我們需要通過(guò)點(diǎn)的形式獲取枚舉集合中的成員:

    console.log(Day.SUNDAY)   // 0
    console.log(Day.MONDAY)   // 1

    說(shuō)完枚舉類型的基本使用,下面就來(lái)看一下常見(jiàn)的枚舉類型。

    1. 數(shù)字枚舉

    在上面的例子中,在僅指定常量命名的情況下,定義的就是一個(gè)默認(rèn)從 0 開(kāi)始遞增的數(shù)字集合,稱之為數(shù)字枚舉。如果想要從其他值開(kāi)始遞增,可以將第一個(gè)值的索引值進(jìn)行指定:

    enum Color {
      Red = 2,
      Blue,
      Yellow
    }
    console.log(Color.Red, Color.Blue, Color.Yellow); // 2 3 4

    可以對(duì)一個(gè)字段指定一個(gè)索引值,那他后面沒(méi)有指定索引值的就會(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)的遞增值了,來(lái)看例子:

    // 初值為計(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í),可以通過(guò) Enum['key'] 或者 Enum.key 的形式獲取到對(duì)應(yīng)的值 value。TypeScript 還支持反向映射,但是反向映射只支持?jǐn)?shù)字枚舉,不支持字符串枚舉。

    來(lái)看下面的例子:

    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è)對(duì)象,生成的代碼中,枚舉類型被編譯成一個(gè)對(duì)象,它包含了正向映射( name -> value)和反向映射( value -> name)。

    下面來(lái)看看上面代碼中的 Status 編譯后的效果:

    {
        200: "Success",
        404: "NotFound",
        500: "Error",
        Error: 500,
        NotFound: 404,
        Success: 200
    }

    可以看到,TypeScript 會(huì)把定義的枚舉值的字段名分別作為對(duì)象的屬性名和屬性值,把枚舉值的字段值分別作為對(duì)象的屬性值和屬性名,同時(shí)添加到對(duì)象中。這樣既可以通過(guò)枚舉值的字段名得到值,也可以通過(guò)枚舉值的值得到字段名。

    4. 異構(gòu)枚舉

    異構(gòu)枚舉就是枚舉值中成員值既有數(shù)字類型又有字符串類型,如下:

    enum Result {
      Faild = 0,
      Success = "Success"
    }

    在開(kāi)發(fā)過(guò)程中不建議使用異步枚舉。因?yàn)橥鶎⒁活愔嫡頌橐粋€(gè)枚舉值時(shí),它們的特點(diǎn)是相似的。比如在做接口請(qǐng)求時(shí)的返回狀態(tài)碼,如果是狀態(tài)碼都是數(shù)值,如果是提示信息,都是字符串,所以在使用枚舉的時(shí)候,往往是可以避免使用異構(gòu)枚舉的,主要是做好類型的整理。

    5. 常量枚舉

    TypeScript中,定義了枚舉值之后,編譯成 JavaScript 的代碼會(huì)創(chuàng)建一個(gè)對(duì)應(yīng)的對(duì)象,這個(gè)對(duì)象可以在程序運(yùn)行時(shí)使用。但是如果使用枚舉只是為了讓程序可讀性好,并不需要編譯后的對(duì)象呢?這樣會(huì)增加一些編譯后的代碼量。TypeScript 中有一個(gè)const enum(常量枚舉),在定義枚舉的語(yǔ)句之前加上const關(guān)鍵字,這樣編譯后的代碼不會(huì)創(chuàng)建這個(gè)對(duì)象,只是會(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

    對(duì)于 Status 的處理,先是定義一個(gè)變量 Status,然后定義一個(gè)立即執(zhí)行函數(shù),在函數(shù)內(nèi)給 Status 添加對(duì)應(yīng)屬性,首先Status[“Off”] = 0是給Status對(duì)象設(shè)置Off屬性,并且值設(shè)為 0,這個(gè)賦值表達(dá)式的返回值是等號(hào)右邊的值,也就是 0,所以Status[Status[“Off”] = 0] = "Off"相當(dāng)于Status[0] = “Off” 。創(chuàng)建了這個(gè)對(duì)象之后,將 Status 的 On 屬性值賦值給 status;再來(lái)看下 animal 的處理,編譯后的代碼并沒(méi)有像Status創(chuàng)建一個(gè)Animal對(duì)象,而是直接把Animal.Dog的值0替換到了const animal = Animal.Dog表達(dá)式的Animal.Dog位置。

    通過(guò)定義常量枚舉,可以以清晰、結(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è)成員和枚舉值本身都可以作為類型來(lái)使用,我們稱這樣的枚舉成員為字面量枚舉成員。

    滿足條件的枚舉成員的值有以下三種:

    • 沒(méi)有初始值的枚舉成員,例如: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. 枚舉合并

    說(shuō)完常見(jiàn)的枚舉類型,最后來(lái)看看枚舉合并的概念。對(duì)于枚舉類型的值,我們可以分開(kāi)進(jìn)行聲明:

    enum Day {
      SUNDAY,
      MONDAY,
      TUESDAY
     }
    
    enum Day {
      WEDNESDAY,
      THURSDAY,
      FRIDAY,
      SATURDAY
     }

    這時(shí) TypeScript 就會(huì)對(duì)這個(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 = {}));

    到此,相信大家對(duì)“如何理解TypeScript枚舉類型”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

    向AI問(wèn)一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI