我们常常会有这样的场景,比如与后端开发约定订单的状态开始是0,未结账是1,运输中是2,运输完成是3,已收货是4。这样的纯数字会使得代码缺乏可读性。枚举就用于这样的场景。枚举可以让我们定义一些名字有意义的常量。使用枚举可以清晰地表达我们的意图。TypeScript支持基于数字枚举和字符串的枚举。

⒈数字枚举

  首先我们举例来看数字枚举

enum OrderStatus{
Start = 1,
Unpaid,
Shipping,
Shipped,
Complete,
}

  就像上面这样,我们通过数字来表达了订单状态。在实际的代码编写时,我们就直接使用OrderStatus.Start来代替原本的数字1,这就使得代码具备了相当的可读性,甚至可以免去冗余的注释。

  在上面的代码中还使用了一个小技巧,当只写Start = 1时,后面的枚举变量就是递增的,当我们不在乎成员的值的时候,这种自增长的行为是很有用处的,但是要注意每个枚举成员的值都是不同的,但你也可以明确地写出每个枚举变量的数字,这取决于具体的业务场景。

  当我们连第一个枚举变量的值都不写的时候,初始值将会为0,后面的枚举类型再依次递增。

enum OrderStatus{
Start,
Unpaid,
Shipping,
Shipped,
Complete,
}

  现在OrderStatus.Start的值为0,通常情况下,在使用这样的写法时,我们其实是不在乎成员变量的具体值的,我们只知道这些值是不同的。

  枚举类型中的值必须是确定的,比如,像下面这样的写法是不被允许的。

enum Example{
A = hello(),
b,
}

  类似这样没有给出确定值的写法在TypeScript中都是不被允许的。

⒉字符串枚举

  字符串枚举的概念与数字枚举有一些细微的差别

  在一个字符串枚举中,所有成员必须都是字符串字面量,且字符串枚举没有递增的含义,字符串枚举的成员都必须手动初始化。 

enum OrderStatus{
Start = 'Start',
Unpaid = 'Unpaid',
Shipping = 'Shipping',
Shipped = 'Shipped',
Complete = 'Complete',
}

  虽然字符串枚举显得繁琐,但相比数字枚举,由于字符串枚举没有自增长的行为,因此字符串枚举能进一步提升可读性,如果你正在调试并且必须要读一个数字枚举的运行时的值,这个值通常是很难读的,即使读取出来它也并不能表达有用的信息,而字符串枚举允许你提供一个运行时有意义的并且可读的值,独立于枚举成员的名字。这使得调试变得更容易。所以在实际的开发中,大家更喜欢使用字符串枚举。

⒊异构枚举

  从技术的角度来说,枚举可以混合字符串和数字成员,但是似乎你并不会这么做,除非你真的想要利用JavaScript运行时的行为,否则我们不建议这样做。

enum OrderStatus{
Start = 'Start',
Unpaid = 1,
Shipping,
Shipped,
Complete,
}

⒋枚举成员的值

  每个枚举成员都带有一个值,它可以是 常量或 经过计算出来的

  当满足如下条件时,枚举成员被当作是常量

    1.当前枚举成员是枚举的第一个成员且没有初始化器,这种情况下它将被赋予常量值 0

enum OrderStatus{
Start, //OrderStatus.Start is 0
Unpaid,
Shipping,
Shipped,
Complete,
}

    2.当前枚举成员不带有初始化器且它之前的枚举成员的值是一个 数字常量。 这种情况下,当前枚举成员的值为它上一个枚举成员的值加1。

enum OrderStatus{
Start = 0,
Unpaid, //OrderStatus.Unpaid is 1
Shipping,
Shipped,
Complete,
}

    3.枚举成员使用 常量枚举表达式初始化。 常数枚举表达式是TypeScript表达式的子集,它可以在编译阶段求值。 当一个表达式满足下面条件之一时,它就是一个常量枚举表达式:

    • 一个枚举表达式字面量(主要是字符串字面量或数字字面量)
    • 一个对之前定义的常量枚举成员的引用(可以是在不同的枚举类型中定义的)
    • 带括号的常量枚举表达式
    • 一元运算符 +-~其中之一应用在了常量枚举表达式
    • 常量枚举表达式做为二元运算符 +-*/%<<>>>>>&|^的操作对象。 若常数枚举表达式求值后为 NaN或 Infinity,则会在编译阶段报错。

  当以上的条件均不满足的情况下,枚举成员被当作是需要计算得出的值:

enum OrderStatus{
None,
Read = 1 << 1,
Write = 1 << 2,
ReadWrite = Read | Write,
G = "123".length
}

⒌枚举成员类型和联合枚举类型

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

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

  1.枚举成员类型

  把符合条件的枚举成员作为类型来使用,例子:

enum ShapeKind {
Circle,
Square
} interface Circle {
kind: ShapeKind.Circle // 使用 ShapeKind.Circle 作为类型,指定接口须有 kind 字段,且类型为 ShapeKind.Circle
radius: number
} interface Square {
kind: ShapeKind.Square // 同上
sideLength: number
} let c: Circle = {
kind: ShapeKind.Square, // Error! 因为接口 Circle 的 kind 被指定为 ShapeKind.Circle类型,所以这里会报错
radius: 100
}

  interface是定义接口,现在简单了解即可。

  2.联合枚举类型

  符合条件的枚举本身可以看作是一个包含所有成员的联合类型,下面例子:

// 枚举 Status 里有两个状态
enum Status {
Off,
On
} // 枚举 Animal 里有两个动物
enum Animal {
Cat,
Dog
} // 接口 Light 中定义 status字段,它是 Status 类型,可以是 Off 或者 On 状态
interface Light {
status: Status
} let lg1: Light = {
status: Status.Off // 正确
} let lg2: Light = {
status: Animal.Cat // error 不能将类型 Animal.Cat 分配给类型 Status
}

⒍运行时的枚举

  枚举是在运行时真正存在的对象,可以把枚举当作对象使用:

enum E {
A,
B
} function func(obj: { A: number }): number {
return obj.A
} console.log(func(E)) //

  代码中,声明了一个函数 func,它的参数是一个对象,且必须包含属性名为 A 的属性,A 的值为数值类型。当调用函数 func 时,把枚举 E 当作符合条件的实参传入,正确运行。

⒎反向映射

  反向映射是数字枚举的一个技巧,这得益于TypeScript在实现数字枚举时的代码编译。

  例如当我们设定了如下一个枚举时:

enum OrderStatus{
A
}

  TypeScript编译器将这段代码编译到JavaScript时是这样的:

var Enum;
(function (Enum) {
Enum[Enum["A"] = 0] = "A";
})(Enum || (Enum = {}));

  生成的代码中,枚举类型被编译成一个对象,它包含了正向映射( key -> value)和反向映射( value -> key)。所以我们既可以通过属性名获取属性值,也可以通过属性值获取属性名。

let a = OrderStatus.A;
let b = OrderStatus[0];
console.log(a);  //0
console.log(b);  //A

  注意:字符串编译后并没有这样的特性,因此,在字符串枚举中没有反向映射。

⒏const 枚举

  定义的枚举,在经过编译器编译后是一个对象,这个对象我们可以在程序运行时使用,前面有说到。但有时定义枚举可能只是为了让程序可读性更好,而不需要编译后的代码,即不需要编译成对象。typescript中考虑到这种情况,所以加入了 const enum (完全嵌入的枚举)。typescript官网有一个在线编译器,来看看下面的例子:

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一样创建了Animal,而是直接把 Animal 中 Dog 值 0 替换到表达式中 Animal.Dog 的位置,这样就节省了生成代码的开销。

⒐外部枚举

  外部枚举用来描述已经存在的枚举类型的形状。

declare enum Enum {
A = 1,
B,
C = 2
}

  外部枚举和非外部枚举之间有一个重要的区别,在正常的枚举里,没有初始化方法的成员被当成常数成员。 对于非常数的外部枚举而言,没有初始化方法时被当做需要经过计算的。

  借鉴文章:https://www.cnblogs.com/wjaaron/p/11672764.html

  

  

  

TypeScript 枚举的更多相关文章

  1. TypeScript 枚举指南

    枚举是受 TypeScript 支持的数据类型.枚举允许您定义一组命名常量.使用它们可以更轻松地记录意图或创建一组不同的案例.枚举大多数用于面向对象的编程语言(如 Java 和 C#)中,现在也可以 ...

  2. typescript枚举,类型推论,类型兼容性,高级类型,Symbols(学习笔记非干货)

    枚举部分 Enumeration part 使用枚举我们可以定义一些有名字的数字常量. 枚举通过 enum关键字来定义. Using enumerations, we can define some ...

  3. typescript枚举字符串型不能使用函数问题

    数字型枚举 enum OrderStatus { Start = 1, Unpaid, Shipping, Shipped, Complete } 或者 enum OrderStatus { Star ...

  4. TypeScript——枚举类型

    enum类型是对JavaScript标准数据类型的一个补充. 在运行环境下编译成对象, 可用属性名索引, 也可用属性值索引.而其实现原理为:反向映射 (如下例)   数字枚举 enum Role { ...

  5. TypeScript入门七:TypeScript的枚举

    关于枚举 数字枚举 字符串枚举 异构枚举 计算的和常量成员 运行时的枚举与反向映射 常量枚举与外部枚举 一.关于枚举 枚举:一个集的枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计 ...

  6. 《三》大话 Typescript 接口

    > 前言: 本文章为 TypeScript 系列文章. 旨在利用碎片时间快速入门 Typescript. 或重新温故 Typescript 查漏补缺.在官方 api 的基础上, 加上一些日常使用 ...

  7. Typescript 最佳实践

    文章列表: <一>大话 TypeScript 基本类型 <二>大话 Typescript 枚举 <三>大话 Typescript 接口 <四>大话 Ty ...

  8. Typescript - 变量类型

    原文:TypeScript基本知识点整理 一.number let num1 : number = 20; let num2 : number = 175.5; let a1 : number = I ...

  9. 浅谈TypeScript,配置文件以及数据类型

    TypeScript在javaScript基础上多了一些拓展特性,多出来的是一些类型系统以及对ES6新特性的支持最终会编译成原始的javaScript, 文件名以.ts结尾,编译过后.js结尾,在an ...

随机推荐

  1. ROS与树莓派的结合

    从零开始学树莓派和ROS 今天写下自己的第一篇博客,记录一下自己的学习历程和学习过程中碰到的各种小问题,供同道者参阅和自己以后回顾用 ,水平不高,我就放开手写吧,反正也不会有人看. 我现在在做毕业设计 ...

  2. 10月清北学堂培训 Day 3

    今天是钟皓曦老师的讲授~ zhx:题很简单,就是恶心一些qwq~ T1 别人只删去一个字符都能AC,我双哈希+并查集只有40?我太菜了啊qwq 考虑到越短的字符串越难压缩,越长的字符串越好压缩,所以我 ...

  3. 如何利用shell或者awk二维数组实现9x9乘法表?

    第一种:利用shell for循环来实现. for i in `seq 1 9`do for j in `seq 1 9` do if [ $i -ge $j ] then echo -en &quo ...

  4. hadoop(1)---hadoop的介绍和几种模式。

    一.什么是hadoop? Hadoop软件库是一个开源框架,允许使用简单的编程模型跨计算机集群分布式处理大型数据集.它旨在从单个服务器扩展到数千台计算机,每台计算机都提供本地计算和存储.库本身不是依靠 ...

  5. Dp优化之决策单调栈优化

    证明:g(i) ≤ g(j)   (i ≤ j) 令 d=g(i) , k<d , 设cut = x表示 f(i) = f(x) + w[x,i]    ( x < i ) 构造一个式子: ...

  6. Invalid Component definition:header

    主要是header不是字符串,而是变量

  7. 2018-2019-2 20165114《网络对抗技术》Exp7 网络欺诈防范

    Exp7 网络欺诈防范 目录 一.实验内容 二.基础问题回答 (1)通常在什么场景下容易受到DNS spoof攻击 (2)在日常生活工作中如何防范以上两攻击方法 三.实践过程记录 3.1简单应用SET ...

  8. OpenResty之ngx.var.VARIABLE

    1. ngx.var.VARIABLE syntax: ngx.var.VAR_NAME context: set_by_lua*, rewrite_by_lua*, access_by_lua*, ...

  9. 虚拟机VMware安装及Linux系统基础配置(CentOS 7)

    PS: 我是 VMware 14 安装 CentOS 7 来配置Linux虚拟机,想要安装 Ubuntu 18.04 的可以自行其他搜或者参考博客:https://blog.csdn.net/gith ...

  10. 微信小程序填坑之路(三):布局适配方案(rpx、px、vw、vh)

    因为小程序是以微信为平台运行的,可以同时运行在android与ios的设备上,所以不可避免的会遇到布局适配问题,特别是在iphone5上,因为屏幕尺寸小的缘故,也是适配问题最多的机型,下面就简单介绍几 ...