技术/翻译

原文链接:TypeScript Data Type - Enum

跟其他多数面向对象语言如Java、C#一样,Typescript同样支持Enum枚举类型。简单来说,枚举允许我们定义一组命名变量,该组变量可以是数字型或字符串型。

枚举类型包括:

  • 数字枚举
  • 字符串枚举
  • 开发式枚举

让我们分布研究下各种枚举的样子:

数字枚举

顾名思义,数字枚举就是保存数值类型的枚举。
我们可以通过关键词enum来定义一个枚举,现在来定义一个枚举PrintMedia

  1. enum PrintMedia {
  2. Newspaper,
  3. Newsletter,
  4. Magazine,
  5. Book
  6. }

上面我们定义了一个名为PrintMedia的枚举,包括四个值分别是:Newspaper,Newsletter,Magazine,Book。需要了解的是枚举的成员变量值默认以数值来存储,第一个值通过是从0开始,并且其他值逐渐递增1,所以PrintMedia的四个值分别是:

Newspaper = 0
Newsletter = 1
Magazine = 2
Book = 3

当然,我们可以改变第一个值的初始值,如下:

enum PrintMedia {
  Newspaper = 1,
  Newsletter,        // 2
  Magazine,        // 3
  Book            // 4
}

我们给第一个元素指定值为1,则其他元素默认在第一个元素值的基础上逐渐递增加1。另外,枚举值不一定要是连续的值,可以指定随机数字:

enum PrintMedia {
    Newspaper = 1,
    Newsletter = 5,
    Magazine = 10,
}

使用枚举作为函数返回值:

function getMediaType(media: string): PrintMedia {
    if (media === 'Foris') {
        return PrintMedia.Magazine
    }
}
const mediaType: PrintMedia = getMediaType('Foris')

数字枚举的成员可以为任何表达式,最终返回一个数值即可;但是所有表达式成员必须在其他初始化成员最前面或最后面,这样TypeScript才能推断表达式应该返回的类型

如下面定义的枚举会导致报错:

enum PrintMedia {
    Newsletter = getPrintMediaCode('newsletter'),
    Newspaper, // Error: Enum member must have initializer
    Book,
    Magazine = Newsletter * 3,
}

// right
enum PrintMedia {
    Newspaper,
    Book,
    Newsletter = getPrintMediaCode('newsletter'),
    Magazine = Newsletter * 3
}
// or
enum PrintMedia {
    Newsletter = getPrintMediaCode('newsletter'),
    Magazine = Newsletter * 3,
    Newspaper = 0,
    Book,
}

字符串枚举

与数字型枚举类似,不过字符串枚举的成员变量值是以字符串来初始化的。字符串枚举的好处是字符串的可读性更好,尤其是我们在调试程序时,字符串要比数字要方便的多。

enum PrintMedia {
    Newspaper = "NEWSPAPER",
    Newsletter = "NEWSLETTER",
    Magazine = "MAGAZINE",
    Book = "BOOK"
}
// Access String Enum 
PrintMedia.Newspaper; //returns NEWSPAPER
PrintMedia['Magazine'];//returns MAGAZINE

上面我们重新定义了一个字符串枚举PrintMedia,同样包括四个值,但是使用字符串来替换数字,此外字符串枚举必须初始化。

开放式枚举

上面讲了数字枚举和字符串枚举,当然也存在一种枚举同时包括字符串和数字:

enum Status { 
    Active = 'ACTIVE', 
    Deactivate = 1, 
    Pending
}

那此时Pending的值应该是什么呢?字符串枚举必须初始化,数字枚举自动根据第一个值递增,所以Pending应该为2。

枚举逆向映射

先来看一下何为逆向映射:

PrintMedia.Magazine; // 3
PrintMedia[3] // Magazine

我们既可以通过成员变量名获取值,也可以根据值获取成员变量名,TypeScript同样支持这种逆向映射。

枚举原理分析

首先可以理解为一个枚举即是一个对象:

var PrintMedia = {}

定义一个成员变量:

PrintMedia['Magazine'] = 0

并且定义逆向映射:

PrintMedia[0] = 'Magazine'

当然,这只是简单实现,实际还要考虑字符串初始化的校验,数字枚举自动递增实现。

模拟枚举:

"use strict";
var PrintMedia;
(function(PrintMedia){
    PrintMedia[PrintMedia["Newspaper"]=1]="Newspaper";
    PrintMedia[PrintMedia["Newsletter"]=2]="Newsletter";
    PrintMedia[PrintMedia["Magazine"]=3]="Magazine";
    PrintMedia[PrintMedia["Book"]=4]="Book";
})(PrintMedia||(PrintMedia={}));

注意: 逆向映射只适用数字枚举,字符串枚举并不支持,在开放式枚举中,也只有数字型枚举变量可以使用。一段代码解释原因:

enum PrintMedia{
    Book='book',
    Hello='book'
}

// js version
"use strict";
var PrintMedia;
(function(PrintMedia){
    PrintMedia["Book"]="book";
    PrintMedia["Hello"]="book";
})(PrintMedia||(PrintMedia={}));

枚举的两个成员变量初始化同一个字符串,如果支持逆向映射,那PrintMedia[‘book’]访问是哪个变量名?


今天又更新了,实在是今天在看TypeScript时看到这篇文章,感觉入门很通俗易懂就在看的时候随手翻译了,给大家分享一下。记得关注我的公众号【也寻常】,我们聊点别的~

公众号二维码.jpg