美文网首页javascriptTypeScript
TypeScript(七)枚举

TypeScript(七)枚举

作者: 一蓑烟雨任平生_cui | 来源:发表于2019-11-13 12:30 被阅读0次

    基础类型中简单介绍过枚举,用于将取值限定在一定范围内或定义一些不具有语义性的常量,使之可以清晰的表达意图。

    数字枚举

    enum Colors {
      red,
      pink,
      blue
    }
    

    编译结果:

    var Colors;
    (function(Colors) {
        Colors[Colors["red"] = 0] = "red";
        Colors[Colors["pink"] = 1] = "pink";
        Colors[Colors["blue"] = 2] = "blue";
    })(Colors || (Colors = {}));
    

    枚举成员的值默认从0开始自增,同时也会对枚举值到枚举名反向映射。

    手动赋值

    可以对单个或者全部枚举成员手动赋值。

    当对某个枚举成员赋值后,该枚举之后未手动赋值的枚举项会接着递增。

    enum Colors {
      red,
      pink = 3,
      blue
    }
    Colors.blue // 4
    
    enum Colors {
      red = 1,
      pink = 3,
      blue = 5
    }
    Colors.blue // 5
    

    如果未手动赋值的枚举项与手动赋值的重复了,TypeScript 编译时不会进行限制:

    enum Colors {
      red = 3,
      pink = 1, 
      blue, 
      black, 
      orange
    }
    
    Colors.red    // 3
    Colors.black  // 3
    Colors[3]     // 'black'
    Colors[3]     // 'black'
    

    以上枚举递增到 3 的时候与前面的 red 的取值重复了,但是 TypeScript 并没有报错,导致 Colors[3] 的值先是 "red",而后又被 "black" 覆盖。编译的结果是如下,所以使用的时候需要注意,不要出现覆盖的情况。

    var Colors;
    (function(Colors) {
        Colors[Colors["red"] = 3] = "red";
        Colors[Colors["pink"] = 1] = "pink";
        Colors[Colors["blue"] = 2] = "blue";
        Colors[Colors["black"] = 3] = "black";
        Colors[Colors["orange"] = 4] = "orange";
    })(Colors || (Colors = {}));
    

    此外手动赋值的枚举项也可以为小数或负数,之后未手动赋值的项的递增步长仍为 1:

    enum Colors {
      red = 1.5,
      pink, 
      blue, 
      black = -1, 
      orange
    }
    
    Colors.pink    // 2.5
    Colors.orange  // 0
    

    常数项和计算所得项

    当给某一个枚举成员设置常量或计算所得值后,其之后的成员必须手动初始化。

    常数项
    const num = 2
    enum Colors {
      pink = 4,
      red = num,
      blue = 4
    }
    

    以上将常量num赋值给枚举成员red,则其之后的成员必须初始化,否则编译报错:

    const num = 2
    enum Colors {
      pink = 4,
      red = num,
      blue
    }
    // Enum member must have initializer.
    
    计算所得项
    function getNum() {
      return 3
    }
    enum Colors {
      red = 1,
      blue = getNum(),
      pink = 6
    }
    
    enum Colors {
      red = 1,
      blue = 'sina'.length,
      pink = 6
    }
    

    反向映射

    除了创建一个以属性名做为对象成员的对象之外,数字枚举的成员还具有反向映射,从枚举值到枚举名。如下:

    enum Colors {
      red
    }
    Colors.red  // 0
    Colors[0]  // 'red'
    

    编译结果:

    var Colors;
    (function (Colors) {
        Colors[Colors["red"] = 0] = "red";
    })(Colors || (Colors = {}));
    
    

    ts编译生成的js代码中,数字枚举类型被编译成一个对象,包含正向映射( key -> value)和反向映射( value -> key)。

    注意:字符串枚举的成员不会生成反向映射。

    字符串枚举

    在一个字符串枚举里,每个成员都必须用字符串字面量,或另外一个字符串枚举成员进行初始化。不可以使用常量枚举或计算值。

    enum Colors {
      red = 'RED',
      pink = 'PINK',
      blue = red
    }
    Colors.blud // 'RED'
    

    编译结果:

    var Colors;
    (function(Colors) {
        Colors["red"] = "RED";
        Colors["pink"] = "PINK";
        Colors["blue"] = "RED";
    })(Colors || (Colors = {}));
    

    由于字符串枚举没有自增行为,所以字符串枚举可以很好的序列化。 换句话说,数字枚举的值通常并不能表达有用的信息(尽管反向映射会有所帮助),但字符串枚举允许提供一个运行时有意义的并且可读的值,独立于枚举成员的名字。

    异构枚举

    从技术的角度来说,枚举可以混合字符串和数字成员:

    enum Colors {
      red = 'RED',
      pink = 'PINK',
      blue = 4
    }
    

    运行时枚举

    枚举在运行时是真正存在的对象,因为ts会将枚举编译成js对象。

    enum Colors {
      red
    }
    
    function bar(obj, key) {
      return obj[key]
    }
    bar(Colors, 'red')
    

    编译结果:

    var Colors;
    (function(Colors) {
        Colors[Colors["red"] = 0] = "red";
    })(Colors || (Colors = {}));
    
    function bar(obj, key) {
        return obj[key];
    }
    bar(Colors, 'red');
    

    const(常量)枚举

    常量枚举通过在枚举上使用 const修饰符来定义。

    const enum Colors {
      red = 4
    }
    function bar() {
      return Colors.red
    }
    bar() // 4
    

    常量枚举与普通枚举不一样它会在编译阶段被删除。因为普通枚举会被编译成js对象,可以将常量枚举理解成在编译阶段首先生成js对象,然后将所有的枚举值计算出来,然后删除对象。

    编译结果:

    function bar() {
        return 4 /* red */ ;
    }
    bar();
    

    所以在运行时不可以使用常量枚举。比如:

    const enum Colors {
      red
    }
    console.log(Colors) 
    // 'const' enums can only be used in property or index access expressions or the right hand side of an import declaration or export assignment or type query.
    //  ("const" 枚举仅可在属性、索引访问表达式、导入声明的右侧、导出分配或类型查询中使用。)
    

    联合枚举与枚举成员的类型

    首先解释字面量枚举成员。

    字面量枚举成员是指不带有初始值的常量枚举成员,或者是值被初始化为以下三种情况的枚举成员。

    • 任何字符串字面量;
    • 任何数字字面量
    • 应用了一元 - 符号的数字字面量
    1. 不带有初始值的常量枚举成员
    enum Colors {
      red
    }
    
    1. 任何字符串字面量:
    enum Colors {
      red = 'RED'
    }
    
    1. 任何数字字面量:
    enum Colors {
      red = 1
    }
    
    1. 应用了一元 - 符号的数字字面量:
    enum Colors {
      red = -10
    }
    

    当所有枚举成员都拥有字面量枚举值时,枚举成员或枚举可以当作类型使用。

    枚举成员类型

    枚举成员类型是指将枚举的某些成员当作类型使用。

    enum Colors {
      red = 'RED'
      pink = 'PINK'
    }
    interface Tomato {
      color: Colors.red
    }
    const tomato: Tomato = {
      color: Colors.red
      // color: Colors.pink // Type 'Colors.pink' is not assignable to type 'Colors.red'.
    }
    

    枚举类型

    枚举类型本身变成了每个枚举成员的联合类型。

    enum Colors {
      red = 'RED',
      pink = 'PINK'
    }
    interface IColor {
      color: Colors
    }
    
    const tomato: IColor = {
      color: Colors.red
    }
    

    相关文章

      网友评论

        本文标题:TypeScript(七)枚举

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