一文让你彻底掌握 TS 枚举

本文深入探讨了 TypeScript 中的枚举,包括基础知识如数字枚举、字符串枚举和异构枚举,以及指定枚举成员值的不同方式。讨论了数字枚举的缺点,如日志输出不友好和松散的类型检查,并推荐使用字符串枚举。枚举的应用场景,如位模式、替代布尔值和创建更安全的字符串常量也得以阐述。同时,介绍了运行时枚举的反向映射以及const枚举的编译表现。文章强调了枚举在编译时的全面性检查和使用keyof操作符的优点。
摘要由CSDN通过智能技术生成

创建了一个 “重学TypeScript” 的微信群,想加群的小伙伴,加我微信“semlinker”,备注重学TS。
本文是 ”重学TS“ 系列,第26 篇文章,感谢您的阅读!

一、基础知识

在 JavaScript 中布尔类型的变量含有有限范围的值,即 truefalse。而在 TypeScript 中使用枚举,你也可以自定义相似的类型。

1.1 数字枚举

这是一个枚举的简单示例:

enum NoYes {
  No,
  Yes,
}

NoYes 被称为枚举 NoYes 的成员。与对象字面量一样,尾随逗号是被允许的。对于 NoYes 枚举我们能够轻易的访问它的成员,比如:

function toChinese(value: NoYes) {
  switch (value) {
    case NoYes.No:
      return '否';
    case NoYes.Yes:
      return '是';
  }
}

assert.equal(toChinese(NoYes.No), '否');
assert.equal(toChinese(NoYes.Yes), '是');
1.1.1 枚举成员值

每个枚举成员都有一个 name 和一个 value。数字枚举成员值的默认类型是 number 类型。也就是说,每个成员的值都是一个数字:

enum NoYes {
  No,
  Yes,
}

assert.equal(NoYes.No, 0);
assert.equal(NoYes.Yes, 1);

除了让 TypeScript 为我们指定枚举成员的值之外,我们还可以手动赋值:

enum NoYes {
  No = 0,
  Yes = 1,
}

这种通过等号的显式赋值称为 initializer。如果枚举中某个成员的值使用显式方式赋值,但后续成员未显示赋值, TypeScript 会基于当前成员的值加 1 作为后续成员的值,比如以下 Enum 枚举中的成员 C:

enum Enum {
  A,
  B,
  C = 4,
  D,
  E = 8,
  F,
}

assert.deepEqual(
  [Enum.A, Enum.B, Enum.C, Enum.D, Enum.E, Enum.F],
  [0, 1, 4, 5, 8, 9]
);
1.2 枚举成员名称的转换

常量的命名有几种约定:

  • 传统上,JavaScript 使用全大写的名称,这是它从 Java 和 C 继承的约定: Number.MAX_VALUE
  • 众所周知的 Symbol 用驼峰式表示,并以小写字母开头,因为它们与属性名称相关: Symbol.asyncIterator
  • TypeScript 手册使用以大写字母开头的驼峰式名称。这是标准的 TypeScript 风格,我们将其用于 NoYes 枚举。
1.3 引用枚举成员名称

与 JavaScript 对象类似,我们可以使用方括号来引用包含非法字符的枚举成员:

enum HttpRequestField {
  'Accept',
  'Accept-Charset',
  'Accept-Datetime',
  'Accept-Encoding',
  'Accept-Language',
}

assert.equal(HttpRequestField['Accept-Charset'], 1);
1.4 基于字符串的枚举

除了数字枚举,我们还可以使用字符串作为枚举成员值:

enum NoYes {
  No = 'No',
  Yes = 'Yes',
}

assert.equal(NoYes.No, 'No');
assert.equal(NoYes.Yes, 'Yes');

对于纯字符串枚举,我们不能省略任何初始化程序。

1.5 异构枚举

最后一种枚举称为异构枚举。异构枚举的成员值是数字和字符串的混合:

enum Enum {
  A,
  B,
  C = 'C',
  D = 'D',
  E = 8,
  F,
}

assert.deepEqual(
  [Enum.A, Enum.B, Enum.C, Enum.D, Enum.E, Enum.F],
  [0, 1, 'C', 'D', 8, 9]
);

请注意,前面提到的规则也适用于此:如果先前的成员值为数字,则我们能省略初始化程序。异构枚举由于其应用较少而很少使用。

目前 TypeScript 只支持将数字和字符串作为枚举成员值。不允许使用其他值,比如 symbols。

二、指定枚举成员值

TypeScript 区分了三种指定枚举成员值的方式:

  • 使用字面量进行初始化:

    • 隐式指定;
    • 通过数字字面量或字符串字面量。
  • 常量枚举成员通过可在编译时计算其结果的表达式初始化。
  • 计算的枚举成员可通过任意表达式初始化。
2.1 字面量枚举成员

如果枚举只有字面量成员,我们可以将这些成员用作类型(类似于数字字面量可以用作类型的方式):

enum NoYes {
  No = 'No',
  Yes = 'Yes',
}

function func(x: NoYes.No) {
  return x;
}

func(NoYes.No); // OK

//@ts-ignore: Argument of type '"No"' is not assignable to
//            parameter of type 'NoYes.No'.
func('No');

//@ts-ignore: Argument of type 'NoYes.Yes' is not assignable to
//            parameter of type 'NoYes.No'.
func(NoYes.Yes);

此外,字面量枚举支持完整性检查(我们将在后面进行介绍)。

TypeScript 2.6 支持在 .ts 文件中通过在报错一行上方使用// @ts-ignore 来忽略错误。

// @ts-ignore 注释会忽略下一行中产生的所有错误。建议实践中在 @ts-ignore之后添加相关提示,解释忽略了什么错误。

  • 16
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值