TypeScript入门教程 之 枚举 Enums
枚举是一种组织相关值集合的方法。许多其他编程语言(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 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
应具有自我解释性,即将变量"False"
成员设置Tristate
为0
。请注意,在JavaScript中,赋值运算符返回分配的值(在本例中为0
)。因此,JavaScript运行时执行的下一件事是Tristate[0] = "False"
。这意味着您可以使用该Tristate
变量将枚举的字符串版本转换为数字,或者将枚举的数字版本转换为字符串。如下所示:
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
因为它允许我对枚举值进行安全的真实检查。
数字枚举作为标志
枚举的一种出色用法是能够将枚举用作Flags
。标志允许您检查一组条件中的某个条件是否为真。考虑以下示例,其中我们具有一组有关动物的属性:
enum AnimalFlags { None = 0, HasClaws = 1 << 0, CanFly = 1 << 1, EatsFish = 1 << 2, Endangered = 1 << 3 }
这里我们使用左移操作符来移动1
周围位的一定水平拿出按位不相交的数字0001
,0010
,0100
和1000
(这些都是小数1
,2
,4
,8
如果你很好奇)。当使用标志时,按位运算符|
(or)/ &
(and)/ ~
(not)是您最好的朋友,并在下面进行演示:
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, }
字符串枚举
我们只看了成员值为number
s的枚举。实际上,您也可以让枚举成员具有字符串值。例如
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 Ile = 0 ;
即编译器:
- 内联枚举(任何用途
0
,而不是Tristate.False
)。 Tristate
因为内联用法,所以不会为该枚举定义生成任何JavaScript(运行时没有变量)。
常量枚举preserveConstEnums
内联具有明显的性能优势。Tristate
运行时没有变量的事实仅仅是编译器通过不生成运行时实际未使用的JavaScript来帮助您。但是,您可能希望编译器仍然为诸如数字到字符串或字符串到数字的查找之类的东西生成枚举定义的JavaScript版本。在这种情况下,您可以使用编译器标志--preserveConstEnums
,它仍将生成var Tristate
定义,以便您可以在运行时使用Tristate["False"]
或Tristate[0]
手动进行定义。这不会以任何方式影响内联。
带有静态函数的枚举
您可以使用声明enum
+ namespace
合并将静态方法添加到枚举。下面演示了一个isBusinessDay
向枚举添加静态成员的示例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
在枚举的延续)来获取生成的代码从以前的定义不会破坏值(即0
,1
...等等的值)。无论如何,TypeScript都会警告您(错误消息In an enum with multiple declarations, only one declaration can omit an initializer for its first enum element.
)。
翻译来源:https://gitee.com/yunwisdoms/typescript-book/blob/master/docs/enums.md