千锋教育-做有情怀、有良心、有品质的职业教育机构

400-811-9990
手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

上海
  • 北京
  • 郑州
  • 武汉
  • 成都
  • 西安
  • 沈阳
  • 广州
  • 南京
  • 深圳
  • 大连
  • 青岛
  • 杭州
  • 重庆
当前位置:重庆千锋IT培训  >  技术干货  >  快速了解TypeScript的枚举与约束

快速了解TypeScript的枚举与约束

来源:千锋教育
发布人:lxl
时间: 2023-03-29 11:38:31

  认识枚举

  ● 在很多计算机语言中都有枚举的概念, 但是 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 这个枚举集合里面的常量, 其他都不行

TypeScript的枚举与约束

  只要你写的不是 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) {}

TypeScript的枚举与约束

  ● 这是因为, 在 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 得到对应的数字, 也可以通过对应的数字得到对应的 key

  enum 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 文件

TypeScript的枚举与约束

  ● 常量枚举

  const enum Pages {

  ONE, // 0

  TWO, // 1

  THREE // 2

  }

  console.log(Pages.ONE)

  console.log(Pages.TWO)

  console.log(Pages.THREE)

  ○ 编译完毕的 js 文件

TypeScript的枚举与约束

  类型约束

  ● 在 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 func = (x: number, y: number) => number

  ● 常量限定

  type color = 'yellow' | 'orange' | 'blue'

  function util(c: color) {}

  util('yellow')

  ○ 这个 color 被限定为了几个值, 将来用 color 去约束一个变量的时候

  ○ 这个变量只能接受这几个值, 这里和 enum 比较像了

  type 和 interface 的共同点

  1. 都可以约束 对象 或者 函数 类型

  ○ interface

  interface User { name: string; age: number }

  interface Func { (x: number): number }

  ○ type

  type 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 继承 type

  type Person = {

  name: string

  age: number

  }

  // 使用 extends 关键字继承自 Person

  interface Student extends Person {

  classRoom: number

  }

  let s: Student = { name: '千锋大前端', age: 10, classRoom: 1 }

  ○ type 使用 交叉(&) 扩展 interface

  interface 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 如果声明重名标识符会报错

TypeScript的枚举与约束

  2. 对于 ES6 模块化语法的默认导出语法

  ○ interface 支持声明的同时进行默认导出

  export default interface User {

  name: string

  age: number

  }

  ○ type 必须先声明, 在默认导出

  type User = {

  name: string

  age: number

  }

  export default User

  ○ 必须要先声明好, 在进行默认导出, 如果直接连写默认导出, 会报错

TypeScript的枚举与约束

  3. type 可以使用 typeof 关键字去获取某一数据类型

  3.type 可以使用 typeof 关键字去获取某一数据类型

  ○ 这里定义了一个 EleType 标识符, 会自动根据 typeof 关键字检测的 box 的类型限制

  4. type 支持使用 in 关键字去遍历成映射类型

  type names = 'firstName' | 'lastName' | 'AKA'

  type nameType = {

  [key in names]: string

  }

  /*

  真实的 nameType 类型

  {

  firstName: string

  lastName: string

  AKA: string

  }

  */

声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。

猜你喜欢LIKE

java的输入语句—— Scanner类

2023-05-04

java数据库操作常识事务的四大特性

2023-05-04

DML数据操作之增加或删除数据

2023-05-04

最新文章NEW

socket是什么?有什么作用?

2023-05-04

Java常量定义是什么

2023-04-28

一分钟带你学多线程

2023-04-28

相关推荐HOT

更多>>

快速通道 更多>>

最新开班信息 更多>>

网友热搜 更多>>