TypeScript的枚举与类型约束
● 上一章我们讲了 TS 的接口
● 这一章, 我们就来聊一聊 TS 的枚举和约束 枚举认识枚举
● 在很多计算机语言中都有枚举的概念, 但是 JS 中是没有枚举这个概念的, 为了弥补这个缺憾 在 TS 加入了枚举类型
● 什么是枚举呢 ?
枚举( mei ju ) : 枚举的意思就是一一列举, 把所有情况都列举出来, 那么取值的时候, 只有这几个可以使用, 其他的都不行
计算机语言里面的枚举( enumerations ) : 把所有的常量放在一个集合内, 让若干个常量变成一组有关联的内容
// 针对一个业务逻辑, 我需要频繁用到四个方向的字符串 const UP = "up" const RIGHT = "right" const DOWN = "down" const LEFT = "left"
● 对于以上四个变量来说
● 我不管做任何逻辑, 我没办法限制你只能使用这四个变量中的一个 // 封装一个功能函数 function util(dir) {}
● 不管用什么方法, 你都没办法限制这个 dir 参数接收到的必须是上面列出的四个方向
● 这个时候, 我们就可以用到枚举了
● 首先, 在 TS 中, 利用 enum 关键字创建一个枚举集合, 把我们需要的四个常量放进去 enum Direction { UP = "up", RIGHT = "right", DOWN = "down", LEFT = "left" }
● 制作了一个 DIrection 枚举集合, 那么就可以用这个集合来对某些数据进行限制了 function util(dir: Direction) {}
● 这就约定了, dir 这个参数的值只能是 Direction 这个枚举集合里面的常量, 其他都不行
● 只要你写的不是 Direction 这个枚举内的内容都不行 数字枚举
● 数字枚举 : 枚举类型中的每一个常量都是数字
● 在 TS 中, 枚举内的每一个常量, 当你不设置值的时候, 默认就是 number 类型 enum Pages { ONE, // 0 TWO, // 1 THREE // 2 }
● 你在枚举内的常量, 第一个默认值是 0, 后面的依次 +1 递增
此时
Pages.ONE => 0
Pages.TWO => 1
Pages.THREE => 2
● 我们也可以自己指定值 enum Pages { ONE = 10, // 10 TWO = 20, // 20 THREE = 30 // 30 }
● 这个时候枚举集合内的常量就是我们指定好的值
● 我们也可以指定部分值 enum Pages { ONE = 10, // 10 TWO, // 11 THREE // 12 }
● 指定常量后面的未指定常量, 就会按照 +1 的规则一次递增
enum Pages { ONE, // 0 TWO = 10, // 10 THREE // 11 }enum Pages { ONE, // 0 TWO = 10, // 10 THREE, // 11 FOUR = 30, // 30 FIVE // 31 }字符串枚举
● 字符串枚举 : 枚举集合中的每一个常量的值都是 string 类型
● 在 TS 内, 你必须要指定一个值, 才可能会出现 string 类型 enum Direction { UP = "up", RIGHT = "right", DOWN = "down", LEFT = "left" }
● 在 TS 中, 枚举常量和任何内容都是不一样的, 包括原始字符串 function util(dir: Direction) {}
● 这是因为, 在 TS 中, 枚举内的每一个常量都是一个独一无二的值
● 所以当你用枚举去限定一个数据的时候, 用的时候也只能用枚举内的值
● 这样也避免你因为手误出现的单词错误, 比如你会不会认为 "form" 和 "from" 是一个单词呢 异构枚举
● 异构枚举 : 其实就是在一个枚举集合内同时混合了数字枚举和字符串枚举
● 但是你大概率是不会这样使用的, 因为我们作为一组数据的集合, 一般不会把数字和字符串混合在一起使用enum Info { ONE, UP = "up", TWO = 2, LEFT = "left" }
● 在这里有一个点需要注意
因为在枚举集合内, 当某一个 key 你没有设置值的时候, 会默认按照上一个的值 +1
所以如果前一个是 字符串枚举, 那么下一个必须要手动赋值, 不然会报错
如果前一个是 数字枚举, 那么下一个可以不必要手动赋值, 会按照上一个 +1 计算枚举合并
● 在 TS 内的枚举, 是支持合并的
● 多个枚举类型可以分开书写, 会在编译的时候自动合并enum Direction { UP = "up", RIGHT = "right", DOWN = "down", LEFT = "left" } enum Direction { TOP = "top", BOTTOM = "bottom" } function util(dir: Direction) {} util(Direction.BOTTOM) util(Direction.LEFT)
● 这里定义的两个枚举都叫做 Direction, 会在编译的时候自动放在一起, 不会出现冲突反向映射
● TS 内的数字枚举, 在编译的时候, 会同时将 key 和 value 分别颠倒编译一次enum Pages { ONE, // 0 TWO, // 1 THREE // 2 }
● 以这个为例, 他是如何进行编译的呢var Pages; (function (Pages) { Pages[Enum["ONE"] = 0] = "ONE" Pages[Enum["TWO"] = 1] = "TWO" Pages[Enum["THREE"] = 2] = "THREE" })(Pages || (Pages = {}));
● 编译完毕的结果Pages = { ONE: 0, TWO: 1, THREE: 2, "0": "ONE", "1": "TWO", "2": "THREE" }
● 也就是说, 我们在 TS 内使用的时候, 如果是数字枚举
● 那么我们可以通过 key 得到对应的数字, 也可以通过对应的数字得到对应的 keyenum Pages { ONE, // 0 TWO, // 1 THREE // 2 } console.log(Pages.ONE) // 0 console.log(Pages.TWO) // 1 console.log(Pages.THREE) // 2 console.log(Pages[0]) // "ONE" console.log(Pages[1]) // "TWO" console.log(Pages[2]) // "THREE"常量枚举
● 常量枚举, 是在枚举的基础上再加上 const 关键字来修饰
● 会在编译的时候, 把枚举内容删除, 只保留编译结果
● 并且对于数字枚举来说, 不在支持反向映射能力, 只能利用 key 来访问
● 非常量枚举enum Pages { ONE, // 0 TWO, // 1 THREE // 2 } console.log(Pages.ONE) console.log(Pages.TWO) console.log(Pages.THREE)
○ 编译完毕的 js 文件
● 常量枚举const enum Pages { ONE, // 0 TWO, // 1 THREE // 2 } console.log(Pages.ONE) console.log(Pages.TWO) console.log(Pages.THREE)
○ 编译完毕的 js 文件
类型约束
● 在 TS 中, 还有一个很神奇的关键字, 叫做 type
● type 又叫做类型别名有很多神奇的功能, 不仅能支持 interface 定义的对象结构, 还支持任何手写类型
● 先来看一个很简单的例子
let n1: number | string | boolean let n2: number | string | boolean let n3: number | string | boolean
● 观察上面一段代码, 我们定义了 n1 和 n2 和 n3 三个变量
○ 对于类型的限制都是 number 或者 string 或者 boolean
● 写起来的时候就非常麻烦
● 这个时候, 我们就可以使用 type 对其进行别名设置type Info = number | string | boolean let n1: Info let n2: Info let n3: Info
● 这样一来, 我们的代码是不是变得简洁了起来
● 可能小伙伴们认为这个用的并不多, 但是 type 也不是只有这一个功能type 的常见使用
● 基本类型的别名type n = number let num: n = 100
○ 这是一个非常基础的使用, 把 number 这个类型起了一个别名叫做 n
○ 今后再用 n 来限制变量的时候, 其实就是在使用 number
● 基本类型联合type i = number | string let str: i = "千锋大前端" str = 100
○ 这就是联合类型, 那 number 或者 string 这个类型齐了一个别名叫做 i
○ 我们再用 i 来限制变量的时候, 这个变量就被限制为了 number 或者 string
● 对象类型type User = { name: string, age: number } let person: User = { name: "千锋大前端", age: 10 }
○ 这就是对象类型, 和 interface 很像, 用处基本一致
● 对象联合类型type User = { name: string, age: number } type Person = User & { gender: boolean } let person: Person = { name: "千锋大前端", age: 10, gender: true }
○ 这就是对象联合类型, 和 interface 的 extends 继承很像
● 元组类型type data = [ number, string ] let info: data = [ 10, "千锋大前端" ]
● 常量限定type color = "yellow" | "orange" | "blue" function util(c: color) {} util("yellow")
○ 这个 color 被限定为了几个值, 将来用 color 去约束一个变量的时候
○ 这个变量只能接受这几个值, 这里和 enum 比较像了
type 和 interface 的共同点
1. 都可以约束 对象 或者 函数 类型
○ interfaceinterface User { name: string; age: number } interface Func { (x: number): number }
○ typetype User = { name: string; age: number } type Func = (x: number) => number
○ 我们看到, 两个定义方式略有区别, 但是后期用法基本一致
2. 扩展类型
○ interface 使用 extends 进行继承interface Person { name: string age: number } // 使用 extends 关键字继承自 Person interface Student extends Person { classRoom: number } let s: Student = { name: "千锋大前端", age: 10, classRoom: 1 }
○ type 使用 交叉(&) 来实现type Person = { name: string age: number } // 使用 交叉(&) type Student = Person & { classRoom: number } let s: Student = { name: "千锋大前端", age: 10, classRoom: 1 }
3. 联合类型
○ interface 使用 extends 继承 typetype Person = { name: string age: number } // 使用 extends 关键字继承自 Person interface Student extends Person { classRoom: number } let s: Student = { name: "千锋大前端", age: 10, classRoom: 1 }
○ type 使用 交叉(&) 扩展 interfaceinterface Person { name: string age: number } // 使用 交叉(&) type Student = Person & { classRoom: number } let s: Student = { name: "千锋大前端", age: 10, classRoom: 1 }type 和 interface 的区别
1. interface 支持多次声明自动合并, type 不支持interface User { name: string age: number } interface User { classRoom: string } /* 真实的 User 接口 { name: string age: number classRoom: string } */
○ type 如果声明重名标识符会报错
2. 对于 ES6 模块化语法的默认导出语法
○ interface 支持声明的同时进行默认导出export default interface User { name: string age: number }
○ type 必须先声明, 在默认导出type User = { name: string age: number } export default User
○ 必须要先声明好, 在进行默认导出, 如果直接连写默认导出, 会报错
3. type 可以使用 typeof 关键字去获取某一数据类型let box = document.querySelector(".box") type EleType = typeof box
○ 这里定义了一个 EleType 标识符, 会自动根据 typeof 关键字检测的 box 的类型限制
4. type 支持使用 in 关键字去遍历成映射类型type names = "firstName" | "lastName" | "AKA" type nameType = { [key in names]: string } /* 真实的 nameType 类型 { firstName: string lastName: string AKA: string } */
3。17百万基金操作A股突然上涨,小高今天这样应对!关键时刻,稳住心态最重要!先赞后看,年赚百万!今天行情的重点1。目前两市成交额总计7045亿元,相比上个交易日同期放量17。94,预估全天成交额在9900亿元左右2。北上资金目前净
积极出海!比亚迪全矩阵车型亮相哥伦比亚品牌展CNMO新闻作为新能源汽车行业的领导者,比亚迪一直积极布局出海业务,加速海外扩张的步伐。3月17日,CNMO从比亚迪汽车官方了解到,在3月2日至12日期间,比亚迪与哥伦比亚经销商M
2023。3。17操作记录卖飞?个人观点,仅做参考,不做买卖依据,各位大佬看完记得点赞,关注,免得后面找不到,持续更新先说结论下午有事,先发了,昨天说的老乡别走,今天来了,然后指数暴涨了,思考下另外个问题,今天赚
阿根廷通胀率达到三位数据埃菲社3月14日报道,阿根廷的通货膨胀率2月加速攀升,31年来按同比计算的通胀率首次超过三位数,导致今年实现减缓居民消费价格指数(CPI)快速上涨的目标变得越来越难以实现。根据阿
拒绝踩坑存储产品选购要点在DIY配件中,最难买的产品其实不是主板显卡或处理器,因为这些产品技术含量较高,一般厂商或小作坊难以参与进来。反而是内存SSD这类存储产品,由于门槛低,闪存颗粒内存颗粒甚至SSD主
20万60000产品!餐饮人都奔赴这场食材预制菜大展深入预制菜全产业链,助力餐企资源对接,一站式整合餐饮上下游资源。3月28日,良之隆2023第十一届中国食材电商节和良之隆2023第十一届预制菜加工与包装设备展览会将在武汉盛大启幕。
以案说险切勿跟风盲目退保鲁网3月18日讯客户刘女士,31周岁,2021年7月1日购买了一份保额为12万的守护百分百保险产品。2022年1月,客户电话联系代理人,告知自己因在某平台看到了一些由个人拍摄的关于
打工新鲜事儿24岁回村当选村长,火了!原标题24岁回村当选村长,火了!3月18日,24岁女大学生回村当村长的故事登上多个平台热搜。极具戏剧性的开局,充满热血的发展,不负众望的成果娃娃村长与彩虹村从890票到160万赞,
今年养老金上涨稳了,19501960年出生的人,都怎么涨?涨多少?点击上方蓝色按钮,即可收听全文,社保当家为您提供视听双体验!2023年养老金上涨稳了,19501960年出生的人,都怎么涨?涨多少钱?养老金从2005年以来一直保持上涨,而2023
警察规范执法既是保护他人也是保护自己教师被举报猥亵后坠亡民警因疏忽自责大有学问今日头条热点34工作玩忽职守,不符合录用条件班主任猥亵学生拒认罪人变老最明显的标志是什么规范执法行为提高执法水平近日,四川某地一涉嫌猥亵儿
GPT的能力?GPT3是目前最先进的自然语言处理模型之一,它具有前所未有的语言理解能力和生成能力。然而,GPT3并不是完美的,还存在许多需要改进的方面,例如模型的精度效率稳定性和可扩展性等。因此