基础篇-枚举类型-《前端知识进阶》

admin 2025-11-01 15:35:03 编程 来源:ZONE.CI 全球网 0 阅读模式
  • 1. 数字枚举
  • 2. 字符串枚举
  • 3. 反向映射
  • 4. 异构枚举
  • 5. 常量枚举
  • 6. 枚举成员类型和联合枚举类型
    • (1)枚举成员类型
    • (2)联合枚举类型
  • 7. 枚举合并

    枚举类型是TypeScript中新增的一种数据类型。使用枚举,可以给一些难以理解的常量赋予一组具有意义的直观的名字,使其更为直观,可以理解枚举就是一个字典。枚举使用 enum 关键字定义,TypeScript 支持数字和字符串的枚举。

    TypeScript 在 ES 原有类型基础上加入枚举类型,使得在 TypeScript 中也可以给一组数值赋予名字,这样对开发者比较友好。枚举类型使用enum来定义:

    1. enum Day {
    2. SUNDAY,
    3. MONDAY,
    4. TUESDAY,
    5. WEDNESDAY,
    6. THURSDAY,
    7. FRIDAY,
    8. SATURDAY
    9. }

    上面定义的枚举类型的Day,它有7个值,TypeScript会为它们每个值分配编号,默认从0开始,在使用时,就可以使用名字而不需要记数字和名称的对应关系了:

    1. enum Day {
    2. SUNDAY = 0,
    3. MONDAY = 1,
    4. TUESDAY = 2,
    5. WEDNESDAY = 3,
    6. THURSDAY = 4,
    7. FRIDAY = 5,
    8. SATURDAY = 6
    9. }

    下面来看看将上面代码转译为 JavaScript 后的效果:

    1. var Day = void 0;
    2. (function (Day) {
    3. Day[Day["SUNDAY"] = 0] = "SUNDAY";
    4. Day[Day["MONDAY"] = 1] = "MONDAY";
    5. Day[Day["TUESDAY"] = 2] = "TUESDAY";
    6. Day[Day["WEDNESDAY"] = 3] = "WEDNESDAY";
    7. Day[Day["THURSDAY"] = 4] = "THURSDAY";
    8. Day[Day["FRIDAY"] = 5] = "FRIDAY";
    9. Day[Day["SATURDAY"] = 6] = "SATURDAY";
    10. })(Day || (Day = {}));

    可以看到,每一个值都被赋予了对应的数字。

    在TypeScript中,我们需要通过点的形式获取枚举集合中的成员:

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

    说完枚举类型的基本使用,下面就来简单介绍一下常见的枚举类型。

    1. 数字枚举

    在上面的例子中,在仅指定常量命名的情况下,定义的就是一个默认从 0 开始递增的数字集合,称之为数字枚举。如果想要从其他值开始递增,可以将第一个值的索引值进行指定:

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

    可以对一个字段指定一个索引值,那他后面没有指定索引值的就会依次加一:

    1. // 指定部分字段,其他使用默认递增索引
    2. enum Status {
    3. Ok = 200,
    4. Created,
    5. Accepted,
    6. BadRequest = 400,
    7. Unauthorized
    8. }
    9. console.log(Status.Created, Status.Accepted, Status.Unauthorized); // 201 202 401

    除此之外,还可以给每个字段指定不连续的任意索引值:

    1. enum Status {
    2. Success = 200,
    3. NotFound = 404,
    4. Error = 500
    5. }
    6. console.log(Status.Success, Status.NotFound, Status.Error); // 200 404 500

    数字枚举在定义值时,可以使用计算值和常量。但是要注意,如果某个字段使用了计算值或常量,那么该字段后面紧接着的字段必须设置初始值,这里不能使用默认的递增值了,来看例子:

    1. // 初值为计算值
    2. const getValue = () => {
    3. return 0;
    4. };
    5. enum ErrorIndex {
    6. a = getValue(),
    7. b, // error 枚举成员必须具有初始化的值
    8. c
    9. }
    10. enum RightIndex {
    11. a = getValue(),
    12. b = 1,
    13. c
    14. }
    15. // 初值为常量
    16. const Start = 1;
    17. enum Index {
    18. a = Start,
    19. b, // error 枚举成员必须具有初始化的值
    20. c
    21. }

    2. 字符串枚举

    TypeScript 将定义值是字符串字面量的枚举称为字符串枚举,字符串枚举值要求每个字段的值都必须是字符串字面量,或者是该枚举值中另一个字符串枚举成员

    1. // 使用字符串字面量
    2. enum Message {
    3. Error = "Sorry, error",
    4. Success = "Hoho, success"
    5. }
    6. console.log(Message.Error); // 'Sorry, error'
    7. // 使用枚举值中其他枚举成员
    8. enum Message {
    9. Error = "error message",
    10. ServerError = Error,
    11. ClientError = Error
    12. }
    13. console.log(Message.Error); // 'error message'
    14. console.log(Message.ServerError); // 'error message'

    注意,这里的其他枚举成员指的是同一个枚举值中的枚举成员,因为字符串枚举不能使用常量或者计算值,所以不能使用其他枚举值中的成员。

    3. 反向映射

    定义枚举类型的值时,可以通过 Enum['key'] 或者 Enum.key 的形式获取到对应的值 value。TypeScript 还支持反向映射,但是反向映射只支持数字枚举,不支持字符串枚举。来看下面的例子:

    1. enum Status {
    2. Success = 200,
    3. NotFound = 404,
    4. Error = 500
    5. }
    6. console.log(Status["Success"]); // 200
    7. console.log(Status[200]); // 'Success'
    8. console.log(Status[Status["Success"]]); // 'Success'

    TypeScript 中定义的枚举,编译之后其实是一个对象,生成的代码中,枚举类型被编译成一个对象,它包含了正向映射( name -> value)和反向映射( value -> name)。下面来看看上面代码中的 Status 编译后的效果:

    1. {
    2. 200: "Success",
    3. 404: "NotFound",
    4. 500: "Error",
    5. Error: 500,
    6. NotFound: 404,
    7. Success: 200
    8. }

    可以看到,TypeScript 会把定义的枚举值的字段名分别作为对象的属性名和属性值,把枚举值的字段值分别作为对象的属性值和属性名,同时添加到对象中。这样既可以通过枚举值的字段名得到值,也可以通过枚举值的值得到字段名。

    4. 异构枚举

    异构枚举就是枚举值中成员值既有数字类型又有字符串类型,如下:

    1. enum Result {
    2. Faild = 0,
    3. Success = "Success"
    4. }

    在开发过程中不建议使用异步枚举。因为往往将一类值整理为一个枚举值时,它们的特点是相似的。比如在做接口请求时的返回状态码,如果是状态码都是数值,如果是提示信息,都是字符串,所以在使用枚举的时候,往往是可以避免使用异构枚举的,主要是做好类型的整理。

    5. 常量枚举

    在TypeScript中,定义了枚举值之后,编译成 JavaScript 的代码会创建一个对应的对象,这个对象可以在程序运行时使用。但是如果使用枚举只是为了让程序可读性好,并不需要编译后的对象呢?这样会增加一些编译后的代码量。TypeScript 中有一个const enum(常量枚举),在定义枚举的语句之前加上const关键字,这样编译后的代码不会创建这个对象,只是会从枚举里拿到相应的值进行替换:

    1. enum Status {
    2. Off,
    3. On
    4. }
    5. const enum Animal {
    6. Dog,
    7. Cat
    8. }
    9. const status = Status.On;
    10. const animal = Animal.Dog;

    上面的代码编译成 JavaScript 之后是这样的:

    1. var Status;
    2. (function(Status) {
    3. Status[(Status["Off"] = 0)] = "Off";
    4. Status[(Status["On"] = 1)] = "On";
    5. })(Status || (Status = {}));
    6. var status = Status.On;
    7. 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位置。

    通过定义常量枚举,可以以清晰、结构化的形式维护相关联的常量集合。而且因为转译后抹除了定义、内联成员值,所以在代码的体积和性能方面并不会比直接内联常量值差。

    6. 枚举成员类型和联合枚举类型

    如果枚举值里所有成员都是字面量类型的值,那么枚举的每个成员和枚举值本身都可以作为类型来使用,我们称这样的枚举成员为字面量枚举成员。满足条件的枚举成员的值有以下三种:

    • 没有初始值的枚举成员,例如:enum E { A }
    • 值为字符串字面量,例如:enum E { A = 'a' }
    • 值为数值字面量,或者带有-符号的数值字面量,例如:enum E { A = 1 }enum E { A = -1 }

    (1)枚举成员类型

    当所有枚举成员都拥有字面量枚举值时,就枚举成员成为了类型:

    1. enum Animal {
    2. Dog = 1,
    3. Cat = 2
    4. }
    5. interface Dog {
    6. type: Animal.Dog;
    7. }
    8. interface Cat {
    9. type: Animal.Cat;
    10. }
    11. let cat: Cat = {
    12. type: Animal.Dog // error [ts] 不能将类型“Animal.Dog”分配给类型“Animal.Cat”
    13. };
    14. let dog: Dog = {
    15. type: Animal.Dog
    16. };

    可以看到,代码的第七行使用Animal.Dog作为类型,指定接口Dog的必须有一个type字段,且类型为Animal.Dog。

    (2)联合枚举类型

    当枚举值符合条件时,这个枚举值就可以看做是一个包含所有成员的联合类型:

    1. enum Status {
    2. Off,
    3. On
    4. }
    5. interface Light {
    6. status: Status;
    7. }
    8. enum Animal {
    9. Dog = 1,
    10. Cat = 2
    11. }
    12. const light1: Light = {
    13. status: Animal.Dog // error 不能将类型“Animal.Dog”分配给类型“Status”
    14. };
    15. const light2: Light = {
    16. status: Status.Off
    17. };
    18. const light3: Light = {
    19. status: Status.On
    20. };

    上面例子定义接口 Light 的 status 字段的类型为枚举值 Status,那么此时 status 的属性值必须为 Status.Off 和 Status.On 中的一个,也就是相当于status: Status.Off | Status.On

    7. 枚举合并

    说完常见的枚举类型,最后来看看枚举合并的概念。对于枚举类型的值,我们可以分开进行声明:

    1. enum Day {
    2. SUNDAY,
    3. MONDAY,
    4. TUESDAY
    5. }
    6. enum Day {
    7. WEDNESDAY,
    8. THURSDAY,
    9. FRIDAY,
    10. SATURDAY
    11. }

    这时 TypeScript 就会对这个枚举值进行合并操作,合并后编译为JavaScript的代码如下:

    1. var Day = void 0;
    2. (function (Day) {
    3. Day[Day["SUNDAY"] = 0] = "SUNDAY";
    4. Day[Day["MONDAY"] = 1] = "MONDAY";
    5. Day[Day["TUESDAY"] = 2] = "TUESDAY";
    6. Day[Day["WEDNESDAY"] = 3] = "WEDNESDAY";
    7. Day[Day["THURSDAY"] = 4] = "THURSDAY";
    8. Day[Day["FRIDAY"] = 5] = "FRIDAY";
    9. Day[Day["SATURDAY"] = 6] = "SATURDAY";
    10. })(Day || (Day = {}));
    以太坊cppgolang区别 编程

    以太坊cppgolang区别

    以太坊是一种去中心化的开源平台,它采用智能合约技术,旨在构建和运行不受干扰的分布式应用程序。作为目前最受欢迎的区块链平台之一,以太坊提供了多种编程语言的支持,其
    progolang 编程

    progolang

    Go语言(Golang)是由Google开发的一门静态类型编程语言。作为一名专业的Golang开发者,我深知这门语言的优势和特点。在本文中,我将介绍Golang
    golangn个发送者 编程

    golangn个发送者

    Golang是一种开源的编程语言,由Google团队开发,旨在提高程序的并发性和简化软件开发过程。在Go语言中,有时需要向多个接收者发送信息。本文将介绍如何在G
    golang技能图谱 编程

    golang技能图谱

    从互联网行业的快速发展到人工智能技术的日益成熟,各种编程语言也应运而生。而在这众多的编程语言中,Golang(即Go)作为一门强大且高效的开发语言备受关注。Go
    评论:0   参与:  18