TypeScript进阶篇 --- 枚举

枚举

枚举(Enum)类型用来取值被限定在一定范围内的场景,比如一周只能偶七天,颜色限定为红绿蓝等。

简单的例子

枚举使用enum关键字来定义:

    enum Days { Sun, Mon, Tue, Wed, Thu, Fri, Sat };
    console.log(Days["Sun"] === 0); // true
    console.log(Days["Mon"] === 1); // true
    console.log(Days["Tue"] === 2); // true
    console.log(Days["Sat"] === 6); // true

    console.log(Days[0] === "Sun"); // true
    console.log(Days[1] === "Mon"); // true
    console.log(Days[2] === "Tue"); // true
    console.log(Days[6] === "Sat"); // true

枚举成员会被赋值从0开始递增的数字,同时也会对枚举值到枚举名进行反向映射。
编译结果:

    var Days = void 0;
    (function (Days) {
        Days[Days["Sun"] = 0] = "Sun";
        Days[Days["Mon"] = 1] = "Mon";
        Days[Days["Tue"] = 2] = "Tue";
        Days[Days["Wed"] = 3] = "Wed";
        Days[Days["Thu"] = 4] = "Thu";
        Days[Days["Fri"] = 5] = "Fri";
        Days[Days["Sat"] = 6] = "Sat";
    })(Days || (Days = {}));

手动赋值

我们也可以给枚举项手动赋值:

    enum Days { Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat };

上例子中,未手动赋值的枚举项会接着上一个枚举项递增。
编译结果:

 (function (Days) {
        Days[Days["Sun"] = 7] = "Sun";
        Days[Days["Mon"] = 1] = "Mon";
        Days[Days["Tue"] = 2] = "Tue";
        Days[Days["Wed"] = 3] = "Wed";
        Days[Days["Thu"] = 4] = "Thu";
        Days[Days["Fri"] = 5] = "Fri";
        Days[Days["Sat"] = 6] = "Sat";
    })(Days || (Days = {}));

如果未手动赋值的枚举项和手动赋值的重复了, TypeScript是不会察觉到这一点的:

    enum Days { Sun = 3, Mon = 1, Tue, Wed, Thu, Fri, Sat };

编译结果:

  var Days = void 0;
    (function (Days) {
        Days[Days["Sun"] = 3] = "Sun";
        Days[Days["Mon"] = 1] = "Mon";
        Days[Days["Tue"] = 2] = "Tue";
        Days[Days["Wed"] = 3] = "Wed";
        Days[Days["Thu"] = 4] = "Thu";
        Days[Days["Fri"] = 5] = "Fri";
        Days[Days["Sat"] = 6] = "Sat";
    })(Days || (Days = {}));

上例子中,递增到3的时候与前面的Sun取值重复了,但是 TypeScript 并没有报错,导致Days[3]的值显示Sun,而后又被Wed覆盖了。
所以使用的时候需要注意,最好不要出现这种覆盖的情况。
手动赋值的枚举项也可以不是数字,此时需要使用类型断言来让tsc无视类型检查。

    enum Days { Sun = 3, Mon = 1, Tue, Wed, Thu, Fri, Sat = <any> "s" };

编译结果:

    var Days = void 0;
    (function (Days) {
        Days[Days["Sun"] = 3] = "Sun";
        Days[Days["Mon"] = 1] = "Mon";
        Days[Days["Tue"] = 2] = "Tue";
        Days[Days["Wed"] = 3] = "Wed";
        Days[Days["Thu"] = 4] = "Thu";
        Days[Days["Fri"] = 5] = "Fri";
        Days[Days["Sat"] = "s"] = "Sat";
    })(Days || (Days = {}));

这种后续的枚举类型必须是手动赋值的:

    enum Days { Sun = 3, Mon = 1, Tue, Wed, Thu = <any> "T", Fri, Sat}; //Fri, Sa 枚举成员必须具有初始化表达式。

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

 enum Days { Sun = 3, Mon = 1.2, Tue, Wed, Thu, Fri, Sat };

编译结果:

    var Days = void 0;
    (function (Days) {
        Days[Days["Sun"] = 3] = "Sun";
        Days[Days["Mon"] = 1.2] = "Mon";
        Days[Days["Tue"] = 2.2] = "Tue";
        Days[Days["Wed"] = 3.2] = "Wed";
        Days[Days["Thu"] = 4.2] = "Thu";
        Days[Days["Fri"] = 5.2] = "Fri";
        Days[Days["Sat"] = 6.2] = "Sat";
    })(Days || (Days = {}));

常数项和计算所得项

枚举项有两种类型:常数项(constant member)和计算所得项(computed member)。
前面我们所举的例子都是常数项,下面是一个计算所得项的例子:

    enum Colors { Red , Green ,Blue = 'blue'.length }

上面例子中,'blue'.length就是一个计算所得项。
上面例子不会报错,但是如果紧接在计算所得项后面的是未手动赋值的项,那么它就会因为无法获得初始值而报错。
常数项和计算所得项的完整定义:
当满足以下条件的时候,枚举成员被当做是常数:

  • 不具有初始化函数并且之前的枚举成员是常数。在这种情况下,当前枚举成员的值为上一个枚举成员的值加1,但第一个枚举元素列外。如果他没有初始化方法,那么他的初始化值为0
  • 枚举成员使用常数枚举表达式初始化。常数枚举的表达式 TypeScript表达式的子集,他可以在编译阶段求职。当一个表达满足下面条件之一时,他就是一个常数枚举表达式:
    • 数字字面量
    • 引用之前定义的常数枚举成员(可以是在不同的枚举类型中定义的),如果这个成员是在同一个枚举类型中订购一的,可以使用非限定名来引用。
    • 带括号的常数枚举表达式
    • +-~一元运算符应用于常数枚举表达式
    • +-*/%<<>>>>>&|^二元运算符,常数枚举表达式作为其一个操作对象。若常数枚举表达式求值后为NaN或Infinity,则会在编译阶段报错。

所有其他情况的没救成员被当做是需要计算得出的值。

常数枚举

常数枚举是使用const enum定义的枚举类型:

    const enum Directives{
        Up,
        Down,
        Left,
        Right
    }

    let directives = [Directives.Up,Directives.Down,Directives.Left,Directives.Right]

常数枚举与普通枚举的区别是,他会在编译阶段被删除,并且不能包好计算成员。
编译结果:

    var directives = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];

假如包含了计算成员,则会在编译阶段报错。

外部枚举

外部枚举(Ambient Enums)是使用declare enum定义的枚举类型:

    declare enum Directives{
        Up,
        Down,
        Left,
        Right
    }
    let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];

之前提到过,declare定义的类型指挥用于编译时的检查,编译结果中会被删除。
上面的编译结果:

    var directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];

外部枚举与声明语句一样,常出现在声明文件中。
同时使用declareconst也是可以的:

    declare const enum Directions {
        Up,
        Down,
        Left,
        Right
    }

    let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];

编译结果:

    var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页