详解 TypeScript枚举(Enum)

  • 枚举
  • 数枚举和数字
  • 数枚举和字符串
  • 改变了一些相关的枚举数
  • 枚举是开放式的
  • 数枚举作为标志
  • 字符串枚举
  • 常量枚举
  • 枚举与静态函数

枚举

枚举是一种组织相关值集合的方法。许多其他编程语言(C / C#/ Java)具有enum数据类型,而JavaScript没有。但是,TypeScript可以。这是TypeScript枚举的示例定义:

enum CardSuit {
    Clubs,
    Diamonds,
    Hearts,
    Spades
}

// Sample usage
var card = CardSuit.Clubs;

// Safety
card = "not a member of card suit"; // Error : string is not assignable to type `CardSuit` 

这些枚举值是number类型 s,因此从此以后我将它们称为Number Enums。

数字枚举和数字

TypeScript枚举是基于数字的。这意味着number可以被分配给enum的一个实例,其他任何与number兼容的东西也可以。

enum Color {
    Red,
    Green,
    Blue
}
var col = Color.Red;
col = 0; // Effectively same as Color.Red  

数字枚举和字符串

在进一步研究枚举之前,让我们看一下它生成的JavaScript,这是一个示例TypeScript:

enum Tristate {
    False,
    True,
    Unknown
}

生成以下JavaScript:

var Tristate;
(function (Tristate) {
    Tristate[Tristate["False"] = 0] = "False";
    Tristate[Tristate["True"] = 1] = "True";
    Tristate[Tristate["Unknown"] = 2] = "Unknown";
})(Tristate || (Tristate = {}));

让我们关注一下Tristate[Tristate["False"] = 0] = "False";这一行。其中 Tristate["False"] = 0应该是不言自明的,即设置Tristate变量的"False"成员为 0。注意,在JavaScript中,赋值操作符返回赋值值(在本例中为 0),因此JavaScript运行时执行的下一件事是 Tristate[0] = "False"。这意味着您可以使用Tristate变量将字符串版本的enum转换为数字,或将数字版本的enum转换为字符串。如下所示:

enum Tristate {
    False,
    True,
    Unknown
}
console.log(Tristate[0]); // "False"
console.log(Tristate["False"]); // 0
console.log(Tristate[Tristate.False]); // "False" because `Tristate.False == 0`

更改与数字枚举关联的数字

默认情况下,枚举是基于0的,然后每个后续值自动加1。作为一个例子,考虑以下情况:

enum Color {
    Red,     // 0
    Green,   // 1
    Blue     // 2
}

但是,可以通过专门分配给任何枚举成员来更改与该枚举成员关联的数字。如下所示,我们从3开始并从那里开始递增:

enum Color {
    DarkRed = 3,  // 3
    DarkGreen,    // 4
    DarkBlue      // 5
}

提示:我通常用来初始化第一个枚举的值= 1,因为它允许我对枚举值进行安全的真实检查。

数字枚举作为标志

枚举的一个出色用法是将枚举用作标志的能力。标记允许您检查一组条件中的某个条件是否为真。考虑下面的例子,我们有一组关于动物的属性:

enum AnimalFlags {
    None           = 0,
    HasClaws       = 1 << 0,
    CanFly         = 1 << 1,
    EatsFish       = 1 << 2,
    Endangered     = 1 << 3
}

这里,我们使用左移运算符将1移动一定级别的位,从而得到按位不相交的数字0010 0100 1000(如果你好奇的话,这些是小数1 2 4 8)。bitwise操作符| (or) / & (and) / ~ (not)是你在使用flags时最好的朋友,如下所示:

enum AnimalFlags {
    None           = 0,
    HasClaws       = 1 << 0,
    CanFly         = 1 << 1,
}
type Animal = {
    flags: AnimalFlags
}

function printAnimalAbilities(animal: Animal) {
    var animalFlags = animal.flags;
    if (animalFlags & AnimalFlags.HasClaws) {
        console.log('animal has claws');
    }
    if (animalFlags & AnimalFlags.CanFly) {
        console.log('animal can fly');
    }
    if (animalFlags == AnimalFlags.None) {
        console.log('nothing');
    }
}

let animal: Animal = { flags: AnimalFlags.None };
printAnimalAbilities(animal); // nothing
animal.flags |= AnimalFlags.HasClaws;
printAnimalAbilities(animal); // animal has claws
animal.flags &= ~AnimalFlags.HasClaws;
printAnimalAbilities(animal); // nothing
animal.flags |= AnimalFlags.HasClaws | AnimalFlags.CanFly;
printAnimalAbilities(animal); // animal has claws, animal can fly 

这里:

  • 我们曾经添加标志|=
  • 和清除标志的组合&=``~
  • | 组合标志

注意:您可以结合使用标志在枚举定义内创建方便的快捷方式,例如:EndangeredFlyingClawedFishEating

enum AnimalFlags {
    None           = 0,
    HasClaws       = 1 << 0,
    CanFly         = 1 << 1,
    EatsFish       = 1 << 2,
    Endangered     = 1 << 3,

    EndangeredFlyingClawedFishEating = HasClaws | CanFly | EatsFish | Endangered,
}

字符串枚举

我们只研究了成员值为数字的枚举。实际上,您也可以拥有带有字符串值的枚举成员。如:

export enum EvidenceTypeEnum {
  UNKNOWN = '',
  PASSPORT_VISA = 'passport_visa',
  PASSPORT = 'passport',
  SIGHTED_STUDENT_CARD = 'sighted_tertiary_edu_id',
  SIGHTED_KEYPASS_CARD = 'sighted_keypass_card',
  SIGHTED_PROOF_OF_AGE_CARD = 'sighted_proof_of_age_card',
}

因为它们提供了有意义的/可调试的字符串值,所以更容易处理和调试。
可以使用这些值进行简单的字符串比较。例如:

// Where `someStringFromBackend` will be '' | 'passport_visa' | 'passport' ... etc.
const value = someStringFromBackend as EvidenceTypeEnum; 

// Sample use in code
if (value === EvidenceTypeEnum.PASSPORT){
    console.log('You provided a passport');
    console.log(value); // `passport`
}

常量枚举

如果您具有如下的枚举定义:

enum Tristate {
    False,
    True,
    Unknown
}

var lie = Tristate.False;

var lie = Tristate.False该行被编译为JavaScript var lie = Tristate.False (是的,输出与输入相同)。这意味着,在执行运行时将需要查找Tristate,然后Tristate.False。为了提高性能,您可以将enum标记为const enum。如下所示:

const enum Tristate {
    False,
    True,
    Unknown
}

var lie = Tristate.False;

生成JavaScript:

var lie = 0 ; 

即编译器:

  1. 内联枚举(任何用途,0而不是Tristate.False)。
  2. 因为它的用法是内联的,所以不会为枚举定义生成任何JavaScript(Tristate运行时没有变量)。

常量枚举preserveConstEnums

内联具有明显的性能优势。事实上,在运行时没有Tristate变量,这只是编译器通过不生成运行时不实际使用的JavaScript来帮助您解决问题。然而,您可能希望编译器仍然生成枚举定义的JavaScript版本,如我们看到的数字到字符串或字符串到数字查找。在这种情况下,您可以使用编译器标志--preserveConstEnums,它仍然会生成变量var Tristate定义,这样您就可以在运行时手动使用Tristate["False"]Tristate[0]。这不会以任何方式影响内联

带有静态函数的枚举

您可以使用声明enum +namespace 合并来向enum添加静态方法。下面演示了一个将静态成员isBusinessDay添加到enum Weekday的例子:

enum Weekday {
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
}
namespace Weekday {
    export function isBusinessDay(day: Weekday) {
        switch (day) {
            case Weekday.Saturday:
            case Weekday.Sunday:
                return false;
            default:
                return true;
        }
    }
}

const mon = Weekday.Monday;
const sun = Weekday.Sunday;
console.log(Weekday.isBusinessDay(mon)); // true
console.log(Weekday.isBusinessDay(sun)); // false

枚举是开放式的

注意:仅当不使用模块时,开放式枚举才有意义。您应该使用模块。因此,本节最后。

这是为再次显示的枚举生成的JavaScript:

var Tristate;
(function (Tristate) {
    Tristate[Tristate["False"] = 0] = "False";
    Tristate[Tristate["True"] = 1] = "True";
    Tristate[Tristate["Unknown"] = 2] = "Unknown";
})(Tristate || (Tristate = {}));

我们已经解释了Tristate[Tristate["False"] = 0] = "False";部分。现在注意周围的代码(function (Tristate) { /*code here */ })(Tristate || (Tristate = {})); 指定(Tristate || (Tristate = {}));部分。这基本上捕获了一个局部变量TriState ,该变量要么指向一个已经定义好的Tristate值,要么用一个新的空{}对象初始化它。
这意味着您可以跨多个文件分割(和扩展)一个枚举定义。例如下面我们将Color的定义分成两个块

enum Color {
    Red,
    Green,
    Blue
}

enum Color {
    DarkRed = 3,
    DarkGreen,
    DarkBlue
}

请注意,您应该在枚举的延续中重新初始化第一个成员(这里DarkRed = 3 ),以获取生成的代码而不是先前定义的clobber值(例如,0 1,…)值)。如果你不这样做,TypeScript会警告您(In an enum with multiple declarations, only one declaration can omit an initializer for its first enum element.)。

你可能感兴趣的:(TypeScript,typescript,前端,Angular,枚举类)