枚举

作者: shuaiutopia | 来源:发表于2020-06-29 13:52 被阅读0次

反向映射

我们可以通过 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"

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

如果一个枚举里所有成员的值都是字面量类型的值,那么这个枚举的每个成员和枚举本身都可以作为类型来使用.

字面量枚举成员是指不带有初始值的常量枚举成员,或者是值被初始化为

  • 任何字符串字面量(例如: "foo", "bar", "baz")例如: enum E { A = 'foo' }
  • 任何数字字面量(例如: 1, 100)例如: enum E { A = 3, B = 4 }
  • 应用了一元 -符号的数字字面量(例如: -1, -100)例如:enum E { A = 1 },enum E { A = -1 }

注意: 枚举类型与数字类型兼容,并且数字类型与枚举类型兼容。不同枚举类型之间是不兼容的.

// 示例1
enum State {
    on,
    off
}
const s: State = 123 // 数字允许

// 示例2
enum State {
    on = 'abc',
    off = 'def'
}
const s: State = 123 // 数字不允许
const s: State = 'abc' // 字符串不允许
const s: State = State.on // 允许

// 示例3
enum State {
    on = 123,
    off = 'def'
}
const s: State = 123 // 数字允许
const s: State = 111 // 数字允许
const s: State = '123' // 字符串不允许
const s: State = State.on // 允许

枚举成员类型

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

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
}

联合枚举类型

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

enum E {
    Foo,
    Bar,
}

function f(x: E) { // 此时的 E 相当于 Foo | Bar
    if (x !== E.Foo || x !== E.Bar) {
        //             ~~~~~~~~~~~
        // Error! Operator '!==' cannot be applied to types 'E.Foo' and 'E.Bar'.
    }
}

这个例子里,我们先检查 x 是否不是 E.Foo。 如果通过了这个检查,然后 || 会发生短路效果, if 语句体里的内容会被执行。 然而,这个检查没有通过,那么 x则 只能为 E.Foo,因此没理由再去检查它是否为 E.Bar

// 枚举 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 枚举

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

// 普通枚举
enum Status{
    Off,
    On
}
// const枚举
const enum Animal{
    Dog,
    Cat
}

const status = Status.On
const animal = Animal.Dog

编译后:

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

特点

const 枚举在编译后因为没有生成相应的对象,因此运行时是不可访问当前枚举对象的,只允许访问枚举成员的值.

// 修饰符 + 关键词 + 枚举名称
const enum NumEnum { a, b, c }

const obj = NumEnum // => Error,运行时不存在
function returnNumber (obj: { a: number }): number {
  return obj.a
}
returnNumber(NumEnum) // => Error,运行时不存在

const A = NumEnum['0'] // => Error,没有生成反向映射,所以不存在该属性
const B = NumEnum['b'] // 正确 => 0/* b */


"compilerOptions": {
  // 保留 const 和 enum 声明该项为 true
  "preserveConstEnums": true
}
// 或者在命令行中添加了 --preserveConstEnums 指令,均会让当前 const 枚举转变为普通枚举
// 即会生成反向映射表;在实际开发中,一般情况你可能需要禁止掉该项,除非想要用于调试;

基于 const 枚举的特点,如果你只是为了生成一组常量并且只需要获取某一个常量, 从性能方面考虑,const 枚举是首选.当然如果你在 tsconfig.json 中指定下面选项:

"compilerOptions": {
  // 保留 const 和 enum 声明该项为 true
  "preserveConstEnums": true
}

或者在命令行中添加了 --preserveConstEnums 指令,均会让当前 const 枚举转变为普通枚举, 即会生成反向映射表. 在实际开发中,一般情况你可能需要禁止掉该项,除非想要用于调试.

相关文章

  • C#枚举及与枚举常数的转换

    1、枚举的定义 2、枚举绑定到comboBox 3、枚举常数转换为枚举string转枚举 数字值转枚举

  • Swift 基础笔记 - 枚举

    枚举 OC定义和使用枚举 Swift定义枚举类型 Swift判断枚举类型 枚举成员类型

  • 枚举类

    1.枚举类型的定义: 枚举类型定义的一般形式为 enum 枚举名{//枚举值表枚举值1;枚举值2;...} 在枚举...

  • 10、枚举与闭包

    枚举 枚举和普通类相比有什么优势 枚举类型、枚举名称与枚举值 枚举的比较运算 两个枚举之间可以使用等值比较(==)...

  • Swift与OC的语法简单对比(常用语法二)

    20- 枚举,枚举原始值,枚举相关值,switch提取枚举关联值 Swift枚举: Swift中的枚举比OC中的枚...

  • Swift 2 学习笔记 10.枚举

    课程来自慕课网liuyubobobo老师 枚举 枚举基础 枚举之原始值 枚举之关联值 枚举递归

  • swift3语法(八)

    枚举/结构体 枚举 定义形式enum 枚举名 { 枚举值} // 例如enum CompassPoint {...

  • C语言基础 之 枚举类型

    枚举类型 枚举类型: 列出所有可能的值 枚举类型的定义 枚举类型定义的一般格式:enum 枚举类型名 {枚举值表}...

  • 枚举

    枚举 Why:为什么需要枚举 What:枚举是什么; How:枚举怎么实现 When:枚举什么时候使用 Where...

  • 枚举的概念及应用

    一、枚举的概念 二、枚举类型的定义 三、枚举变量的定义 四、枚举使用的注意 五、枚举变量的基本操作 五、枚举变量的...

网友评论

    本文标题:枚举

    本文链接:https://www.haomeiwen.com/subject/pauofktx.html