从0开始学习TypeScript-枚举

129 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

今天是我学习Typescript的第4天,今天学习TypeScript枚举类型。 利用枚举我们可以定义一些带名字的常量,使用枚举可以清晰地表达意图或创建一组有区别的用例,TypeScript支持数字的和基于字符串的枚举。

1.数字枚举

看看数字枚举,如果我们使用过C#或者Java语言应该会很熟悉,我们定义了一个日志类型的数字枚举,Info使用初始化为1,其余的成员会从1开始自动增长 Warn 2, Error 3, Debug 4。

//定义一个日志类型的枚举
enum LogType {
    Info = 1,
    Warn,
    Error,
    Debug
}

不使用初始化器现在Info的值为0,Warn的值为1,当我们不重点关心成员的值的时候,可以使用这种自增长的方式,但是需要注意每个枚举成员的值都是不同的。

//不使用初始化器定义一个日志类型的枚举
enum LogType {
    Info ,
    Warn,
    Error,
    Debug
}

在调用中使用枚举很简单,通过枚举的属性来访问枚举成员,和枚举的名字来访问枚举类型:

enum Response {
    No = 0,
    Yes = 1,
}
//接收一个string和枚举类型参数
function respond(recipient: string, message: Response): void {
}
//传入枚举类型的参数值
respond("Princess Caroline", Response.Yes)

下面的情况是会报错的:

enum DemoEnum {
    A = getSomeValue(),
    B, // 因为a初始化了,所以b应该也要初始化
}
2.字符串枚举

字符串枚举的概念和数字类型的有细微运行时的差别,在一个字符串枚举里,每个成员都必须用字符串字面量,或另外一个字符串枚举成员进行初始化,由于字符串枚举没有自增长的行为,但是可以很好的序列化,如果正在调试并且必须要读一个数字枚举的运行时的值,这个值读取有点麻烦的 ,字符串枚举允许你提供一个运行时有意义的并且可读的值,独立于枚举成员的名字。

enum LogType {
    Info ="info" ,
    Warn = "Warn",
    Error = "Error",
    Debug = "Debug"
}

异构枚举可以混合字符串和数字成员,但是不建议这么做,除非确实需要在运行时获取枚举值

enum BooleanLikeHeterogeneousEnum {
    No = 0,
    Yes = "YES",
}

计算和常量成员,每个枚举成员都带有一个值,它可以是常量或计算出来的,当满足如下条件时,枚举成员被当作是常量,它是枚举的第一个成员且没有初始化器,这种情况下它被赋值为0,它不带有初始化器且它之前的枚举成员是一个 数字常量。 这种情况下,当前枚举成员的值为它上一个枚举成员的值加1。

enum E { X }
enum E1 { X, Y, Z }
enum E2 {
    A = 1, B, C
}

枚举成员使用 常量枚举表达式初始化,常数枚举表达式是TypeScript表达式的子集,可以在编译阶段求值,当一个表达式满足下面条件之一时,就是一个常量枚举表达式:

  1. 一个枚举表达式字面量(主要是字符串字面量或数字字面量)
  2. 一个对之前定义的常量枚举成员的引用(可以是在不同的枚举类型中定义的)
  3. 带括号的常量枚举表达式
  4. 一元运算符 +, -, ~其中之一应用在了常量枚举表达式
  5. 常量枚举表达式做为二元运算符 +, -, *, /, %, <<, >>, >>>, &, |, ^的操作对象。 若常数枚举表达式求值后为 NaN或 Infinity,则会在编译阶段报错。 所有其它情况的枚举成员被当作是需要计算得出的值。
enum FileAccess {
    None,
    Read    = 1 << 1,
    Write   = 1 << 2,
    ReadWrite  = Read | Write,
    G = "123".length
}

存在一种特殊的非计算的常量枚举成员的子集:字面量枚举成员。 字面量枚举成员是指不带有初始值的常量枚举成员,或者是值被初始化为

  1. 任何字符串字面量(例如: "foo", "bar", "baz")
  2. 任何数字字面量(例如: 1, 100)
  3. 应用了一元 -符号的数字字面量(例如: -1, -100)

当所有枚举成员都拥有字面量枚举值时,会带有一种特殊的语义,首先枚举成员成为了类型,例如我们可以说某些成员只能是枚举成员的值:

enum ShapeKind {
    Circle,
    Square,
}

interface Circle {
    kind: ShapeKind.Circle;
    radius: number;
}

interface Square {
    kind: ShapeKind.Square;
    sideLength: number;
}

let c: Circle = {
    kind: ShapeKind.Square,
    radius: 100,
}