在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
数字枚举数字枚举,即枚举里所有属性的值都是数字类型,先看这段代码: enum Colors { Red, Blue, Yellow } console.log(Colors.Red) // 0 console.log(Colors.Blue) // 1 console.log(Colors.Yellow) // 2
之前也提到过,当枚举里的属性没指定具体值时,默认值是从 0 开始依次排列,你也可以自己指定具体值,剩下的也是依次递增: enum Colors { Red, Blue = 5, Yellow } console.log(Colors.Red) // 0 console.log(Colors.Blue) // 5 console.log(Colors.Yellow) // 6
另外,数字枚举在定义值的时候,可以是 常量 或者是 计算出来的。当满足以下条件时,枚举成员可以看作常量: 1. 它是枚举的第一个成员且没有初始化,这种情况下它被赋予值 enum Colors { Red }
2. 它未初始化器且它之前的枚举成员是一个 数字常量。 这种情况下,当前枚举成员的值为它上一个枚举成员的值加1。 enum List1 { X, Y, Z } enum List2 { A = 1, B, C } // List1中没初始化,X满足第一个条件,是常量 0,Y 和 Z 没初始化且之前的成员是 数字常量,所以List1所有成员都是常量 // List2 中A直接指定为常量 1,B,C 递增为2,3,List2中也都是常量
3. 枚举成员使用 常量枚举表达式初始化。当一个表达式满足下面条件之一时,它就是一个常量枚举表达式:
所有其它情况的枚举成员被当作是需要计算得出的值。例如: const getValue = () => { return 0 } enum List { A = getValue(), B = 2, // 此处必须要初始化值,不然编译不通过 C } console.log(List.A) // 0 console.log(List.B) // 2 console.log(List.C) // 3 A的值是被计算出来的。注意注释部分,如果某个属性的值是计算出来的,那么它后面一位的成员必须要初始化值。
反向映射我们可以通过 Enum[key] 或者 Enum.key 的方式获取到对应的值。typescript 还支持反向映射,即可以通过值来获取键,不过反向映射只支持数字枚举。下面是个例子: enum Status { Success = 200, NotFound = 404, Error = 500 } console.log(Status.Success) // 200 console.log(Status[200]) // Success console.log(Status[Status.Success]) // Success
字符串枚举字符串枚举值要求每个字段的值都必须是字符串字面量,或者是另外一个字符串枚举成员,如下: enum Str { Str1 = 'this is string one', Str2 = 'this is string two', Str3 = Str1 // 这里引用了Str1的值 } console.log(Str.Str1) // this is string one console.log(Str.Str2) // this is string two console.log(Str.Str3) // this is string one
异构枚举异构枚举是指,枚举可以混合字符串和数字成员,如: enum Enum { A = 0, B = 'hello' } console.log(Enum.A) // 0 console.log(Enum.B) // hello 这种混合值类型的枚举通常是不需要的,不建议使用。因为往往我们将一类值整理为一个枚举时,它们的特点都是相似的。比如我们在做接口请求时的返回状态码,如果是状态码都是数值,如果是提示信息,都是字符串。
枚举成员类型和联合枚举类型如果一个枚举里所有成员的值都是字面量类型的值,那么这个枚举的每个成员和枚举本身都可以作为类型来使用。字面量枚举成员需满足以下条件:
(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)) // 0 代码中,声明了一个函数 func,它的参数是一个对象,且必须包含属性名为 A 的属性,A 的值为数值类型。当调用函数 func 时,把枚举 E 当作符合条件的实参传入,正确运行。
const enum定义的枚举,在经过编译器编译后是一个对象,这个对象我们可以在程序运行时使用,前面有说到。但有时定义枚举可能只是为了让程序可读性更好,而不需要编译后的代码,即不需要编译成对象。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 的位置,这样就节省了生成代码的开销。 |
请发表评论