TypeScript入门——扩展类型之枚举
共 4165字,需浏览 9分钟
·
2021-09-12 00:28
📌 扩展类型——枚举
在上一篇文章中聊到了很多TS
基础类型,那为什么又出现了扩展类型枚举
,我们都知道任何东西都不是平白无故就出现的,都是为了解决特定的问题。枚举
只是扩展类型其中之一,比如说还有类型别名
,接口
,类
那么枚举
是什么意思呢?
📢
枚举
就是把一卡车西瓜一个一个摆在摊子上的过程。
有什么作用?
📢
枚举
通常用来约束某个变量的取值范围,当然不仅仅是变量,还有函数的参数
或者函数的返回值
,比如说约束变量sex
性别的范围,不是男就是女了,不可能是不男不女吧😂
看过我上一篇文章的小伙伴也许会回忆到当时文章中也定义了变量gender
性别取值范围,当时是用字面量
配合联合类型
处理的
举个栗子🌰:
//通过字面量配合联合类型也能达到约束变量的目的
let gender : "男" | "女";
字面量
配合联合类型
也能达到约束变量的目的,那么它和枚举
有什么区别呢?不用想,肯定是遇到解决不了的问题,否则整个枚举出来多此一举没意义。接下来我会详细地介绍,你可以学到:
枚举出现的契机是什么 它解决了什么问题
✨ 字面量类型的问题
🍍 1. 在类型约束位置会产生重复代码,可以使用类型别名
解决该问题
举个栗子🌰:
我们在代码中定义一个gender变量
,类型约束为男
或者女
,gender只能赋值男或者女,其它值不行,接下来有个查询用户的函数searchUsers
,这个函数是根据性别进行查询用户的,如下:
//定义一个gender变量,并且约束为男或者女
let gender : "男" | "女";
//gender可以赋值为男或者女
gender = "女";
gender = "男";
//根据性别查询函数
function searchUsers(g:"男" | "女") {
}
从代码中可以看到变量gender约束
跟函数参数约束
产生相同代码"男" | "女"
,看过上一篇文章的小伙伴也许已经按捺不住了,因为上一篇文章提到过一个类型别名
,它是可以解决这个问题的,如下:
//定义一个类型别名
type Gender = "男" | "女";
//定义一个gender变量,并且约束为男或者女
let gender : Gender;
//gender可以赋值为男或者女
gender = "女";
gender = "男";
//根据性别查询函数
function searchUsers(g:Gender) {
}
所以在类型约束位置会产生重复代码,可以使用类型别名
解决该问题。但是其它问题是没有办法通过类型别名来解决的
🍉 2. 逻辑含义和真实的值产生了混淆,会导致当修改真实值的时候,产生大量修改
举个栗子🌰:
//定义一个类型别名
type Gender = "男" | "女";
//定义一个gender变量,并且约束为男或者女
let gender : Gender;
//gender可以赋值为男或者女
gender = "女";
gender = "男";
//根据性别查询函数
function searchUsers(g:Gender) {
}
上面代码中定义了类型别名Gender
并且约束为男
或者女
,在后续写代码过程中,肯定会给gender赋值男或女,我们可以想象在几万行代码中大量用到gender变量进行赋值,有一天没吃药的产品经理提了个需求:性别用男女约束太俗了,显得没有档次,换个美女
和帅哥
,如下:
//定义一个类型别名
type Gender = "帅哥" | "美女";
//定义一个gender变量,并且约束为男或者女
let gender : Gender;
//gender可以赋值为男或者女
gender = "女";
gender = "男";
//根据性别查询函数
function searchUsers(g:Gender) {
}
换成美女
和帅哥
后是不是要疯了,几十万行代码中大量使用了变量gender赋值为字面量
,约束名一改,后面所有用到的地方都要跟着改,产生大量的修改,为什么会这样呢?根本原因是将逻辑含义和真实的值混淆在了一起,目前约束的美女和帅哥是真实的值,但不管是帅哥、美女,还是男、女都是一个含义,都表示生物学上的性别男和女,使用字面量类型的时候会导致真实的值和逻辑含义的值是对应的,但是在给变量赋值的时候只能赋值为真实的值,逻辑含义的值不变,但真实的值却变了,就产生了大量的修改,这个问题靠类型别名
是没法解决的
🍇 3. 字面量类型不会进入到编译结果
字面量类型是不会参与编译,运行完成后会消失,如下:
如果我们想在TS
中动态读取变量中有哪些取值并显示在页面上,是做不到的,因为TS
在编译的时候已经丢失了变量约束信息。
第二个和第三个问题想要解决就需要靠枚举
了
🍀 枚举的 “道”
🥕 1. 如何定义一个枚举?
//枚举字段表示性别有哪些取值
enum 枚举名 {
枚举字段1:值1,
枚举字段2:值2,
枚举字段3:值3,
}
//以性别为例
enum Gender {
male = "美女",
female = "帅哥",
}
从上述枚举定义来看,控而已发现有两个值,一个枚举字段名
,另一个就是值
,之所以会有两个值,就是解决逻辑含义和真实的值所产生的混淆
,而在枚举中将逻辑含义和真实的值分开了,左边是逻辑含义值,右边是真实的值,有了枚举之后就不再需要类型别名了,对字面量类型出现问题的代码进行修改:
//定义一个类型别名
//type Gender = "帅哥" | "美女";
//换成枚举
enum Gender {
male = "美女",
female = "帅哥",
}
//定义一个gender变量,并且约束为男或者女
let gender : Gender;
//gender可以赋值为男或者女
//gender = "女";
//gender = "男";
//使用了枚举之后,就不能用真实的值进行赋值了
gender = Gender.male;
gender = Gender.female;
//根据性别查询函数
function searchUsers(g:Gender) {
}
如此就解决了字面量类型中第二个问题:逻辑含义和真实的值产生的混淆
,一旦修改真实的值,造成后续大量代码的修改。使用了枚举之后将来直接修改真实的值就可以了,仅需要改一个地方即可,因为后续所有的代码都是用的是逻辑含义的值,这是不会变化的。
枚举另外一个好处就是,枚举会参与代码的编译,它会出现编译的结果中,枚举在JS中表现为对象
,如下:
由于TS中使用了中文,所以它会进行unicode编码
,编译后的JS文件中,首先声明了一个变量Gender
,然后将Gender
传入函数,如果Gender
没有值,那么赋值为一个对象,随后给对象中添加一条属性male
,赋值为美女
,以及female
赋值为帅哥
,因此可以发现枚举是会参与代码的编译,所以我们能在代码编译运行阶段动态的打印枚举中的属性值。如下:
然而之前的类型别名
是做不到的,因为类型别名在编译的时候会消失,而枚举则不会。
因此如果我们需要在运行的过程中使用某个取值范围的话,应该使用枚举,而且防止未来修改大量的代码,应当将逻辑含义跟真实的值分开,也应当使用枚举
📢 紧急通知: 翠花小姐姐来了
翠花小姐姐
提了一个问题:那我们该何时用类型别名?有何时用枚举呢?
👉 解答:
实际上不用纠结,只要是取值范围都可以用枚举
,用它准没错😁
🍄 2. 枚举的规则
枚举的值可以是字符串或数字
字符串刚刚已经说过了,枚举性别用的就是字符串,我们把值为数字的称为
数字枚举
数字枚举的值会自动自增,只有数字有这个特点
举个栗子🌰:
定义了一个
data
枚举,是周一到星期天的字段值,当给Monday
赋值为1
时,其它值会根据上一个值依次自增,如果第一个值没有赋值,那么它会从0
开始,数字枚举的编译结果和字符串枚举编译的结果有差异
这是数字枚举编译后的结果
🌽 3. 枚举的最佳实践
尽量不要在一个枚举中既出现字符串字段,又出现数字字段 使用枚举时,尽量使用枚举字段的名称,而不使用真实的值,就是把逻辑的值和真实的值分开 能用枚举就用枚举,使用类型别名,那两个问题逃不掉