详解 TypeScript 枚举类型


Posted in Javascript onNovember 02, 2021

前言:

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

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

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
}

2. 字符串枚举

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'

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

3. 反向映射

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

来看下面的例子:

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 会把定义的枚举值的字段名分别作为对象的属性名和属性值,把枚举值的字段值分别作为对象的属性值和属性名,同时添加到对象中。这样既可以通过枚举值的字段名得到值,也可以通过枚举值的值得到字段名。

4. 异构枚举

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

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

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

5. 常量枚举

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位置。

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

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

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

满足条件的枚举成员的值有以下三种:

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

(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

(2)联合枚举类型

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

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

7. 枚举合并

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

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 枚举类型的文章就介绍到这了,更多相关TypeScript 枚举类型内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
基于jquery的可多选的下拉列表框
Jul 20 Javascript
jquery实现动态菜单的实例代码
Nov 28 Javascript
实现点击下箭头变上箭头来回切换的两种方法【推荐】
Dec 14 Javascript
JS判断鼠标进入容器的方向与window.open新窗口被拦截的问题
Dec 23 Javascript
微信小程序url与token设置详解
Sep 26 Javascript
js实现Tab选项卡切换效果
Jul 17 Javascript
vue组件中使用iframe元素的示例代码
Dec 13 Javascript
vue2.0 datepicker使用方法
Feb 04 Javascript
Vue cli3 库模式搭建组件库并发布到 npm的流程
Oct 12 Javascript
js嵌套的数组扁平化:将多维数组变成一维数组以及push()与concat()区别的讲解
Jan 19 Javascript
Vue实现回到顶部和底部动画效果
Jul 31 Javascript
vue项目开启Gzip压缩和性能优化操作
Oct 26 Javascript
前端JavaScript大管家 package.json
JavaScript 原型与原型链详情
javascript实现计算器功能详解流程
JS创建或填充任意长度数组的小技巧汇总
Oct 24 #Javascript
一文彻底理解js原生语法prototype,__proto__和constructor
Oct 24 #Javascript
javascript遍历对象的五种方式实例代码
Oct 24 #Javascript
低门槛开发iOS、Android、小程序应用的前端框架详解
Oct 16 #Javascript
You might like
PHP生成加减算法方式的验证码实例
2018/03/12 PHP
js 未结束的字符串常量错误解决方法
2010/06/13 Javascript
jQuery中判断一个元素是否为另一个元素的子元素(或者其本身)
2012/03/21 Javascript
jQuery居中元素scrollleft计算方法示例
2017/01/16 Javascript
jQuery学习之DOM节点的插入方法总结
2017/01/22 Javascript
jQuery插件echarts去掉垂直网格线用法示例
2017/03/03 Javascript
vue构建单页面应用实战
2017/04/10 Javascript
Angularjs中ng-repeat的简单实例
2017/08/25 Javascript
AngularJS表单验证功能
2017/10/19 Javascript
使用 js 简单的实现 bind、call 、aplly代码实例
2019/09/07 Javascript
VScode格式化ESlint方法(最全最好用方法)
2019/09/10 Javascript
JavaScript使用百度ECharts插件绘制饼图操作示例
2019/11/26 Javascript
简单了解vue 插值表达式Mustache
2020/07/22 Javascript
[01:38]DOTA2第二届亚洲邀请赛中国区预选赛出线战队晋级之路
2017/01/17 DOTA
[03:33]TI9战队采访 - Infamous
2019/08/20 DOTA
跟老齐学Python之??碌某?? target=
2014/09/12 Python
python实现下载整个ftp目录的方法
2017/01/17 Python
使用Python对MySQL数据操作
2017/04/06 Python
python调用OpenCV实现人脸识别功能
2018/05/25 Python
详解Python if-elif-else知识点
2018/06/11 Python
利用Python将数值型特征进行离散化操作的方法
2018/11/06 Python
Python编程图形库之Pillow使用方法讲解
2018/12/28 Python
解决python字典对值(值为列表)赋值出现重复的问题
2019/01/20 Python
详解python中sort排序使用
2019/03/23 Python
python 整数越界问题详解
2019/06/27 Python
python常用数据重复项处理方法
2019/11/22 Python
python ftplib模块使用代码实例
2019/12/31 Python
浅谈python的elementtree模块处理中文注意事项
2020/03/06 Python
python requests.get带header
2020/05/05 Python
Pycharm及python安装详细教程(图解)
2020/07/31 Python
python如何调用php文件中的函数详解
2020/12/29 Python
施华洛世奇水晶荷兰官方网站:SWAROVSKI荷兰
2017/05/12 全球购物
巴西女装购物网站:Eclectic
2018/04/24 全球购物
银行求职信
2014/05/31 职场文书
纪检干部现实表现材料
2014/08/21 职场文书
机关干部四风问题自我剖析及整改措施
2014/10/26 职场文书