TypeScript 枚举(Enum)详解
目录
- 概述
- 基本用法
- 枚举类型
- 高级特性
- 最佳实践
- 注意事项
概述
枚举(Enum)是 TypeScript 中用于定义一组命名常量的特性。它可以帮助我们更好地组织和管理相关的常量值。
为什么使用枚举?
- 提供更好的代码可读性
- 限制变量的可能取值
- 提供类型安全
- 自动编号功能
基本用法
1. 数字枚举
// 基本数字枚举
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right // 3
}
// 设置起始值
enum StatusCode {
OK = 200,
NotFound = 404,
Error = 500
}
// 使用枚举
let dir: Direction = Direction.Up;
let status: StatusCode = StatusCode.OK;
2. 字符串枚举
enum Color {
Red = "RED",
Green = "GREEN",
Blue = "BLUE"
}
// 使用字符串枚举
let color: Color = Color.Red;
console.log(color); // "RED"
3. 异构枚举
// 混合字符串和数字
enum Mixed {
No = 0,
Yes = "YES",
}
枚举类型
1. 常量枚举
// 使用 const 声明的枚举
const enum LoadingState {
Idle = "IDLE",
Loading = "LOADING",
Success = "SUCCESS",
Error = "ERROR"
}
// 编译后直接内联值
const state = LoadingState.Loading; // 直接编译为: "LOADING"
2. 计算枚举
enum Calculated {
A = 1,
B = A * 2,
C = B * 2,
// 计算值
D = Math.floor(Math.random() * 100),
// 引用其他常量
E = '123'.length
}
3. 反向映射
enum AccessMode {
Read = 1,
Write = 2,
ReadWrite = Read | Write
}
// 数字枚举支持反向映射
console.log(AccessMode[1]); // "Read"
console.log(AccessMode["Read"]); // 1
高级特性
1. 联合枚举类型
enum TriState {
True = 1,
False = 0,
Unknown = -1
}
// 使用联合类型
function processState(state: TriState) {
switch (state) {
case TriState.True:
return "是";
case TriState.False:
return "否";
case TriState.Unknown:
return "未知";
}
}
2. 枚举成员类型
enum ShapeKind {
Circle,
Square
}
interface Circle {
kind: ShapeKind.Circle;
radius: number;
}
interface Square {
kind: ShapeKind.Square;
sideLength: number;
}
// 使用枚举成员作为类型
function getArea(shape: Circle | Square): number {
switch (shape.kind) {
case ShapeKind.Circle:
return Math.PI * shape.radius ** 2;
case ShapeKind.Square:
return shape.sideLength ** 2;
}
}
3. 运行时枚举
enum ApiStatus {
OK = 200,
NotFound = 404,
Error = 500
}
// 枚举在运行时是真实存在的对象
function isSuccessStatus(status: number): boolean {
return status === ApiStatus.OK;
}
// 遍历枚举
function getEnumNames(enumObj: any): string[] {
return Object.keys(enumObj).filter(key => isNaN(Number(key)));
}
最佳实践
1. 使用常量枚举提高性能
// 推荐:使用常量枚举
const enum HttpMethod {
GET = "GET",
POST = "POST",
PUT = "PUT",
DELETE = "DELETE"
}
// 避免:普通枚举会生成额外代码
enum HttpMethod {
GET = "GET",
POST = "POST",
PUT = "PUT",
DELETE = "DELETE"
}
2. 合理使用字符串枚举
// 好的实践:使用字符串枚举提高可读性
enum LogLevel {
Debug = "DEBUG",
Info = "INFO",
Warn = "WARN",
Error = "ERROR"
}
// 避免:数字枚举可能造成混淆
enum LogLevel {
Debug, // 0
Info, // 1
Warn, // 2
Error // 3
}
3. 使用枚举替代魔法字符串
// 不好的写法
function setUserRole(role: string) {
if (role === "admin" || role === "user" || role === "guest") {
// ...
}
}
// 好的写法
enum UserRole {
Admin = "admin",
User = "user",
Guest = "guest"
}
function setUserRole(role: UserRole) {
// ...
}
注意事项
1. 枚举成员的不可变性
enum Weekday {
Monday,
Tuesday
}
// 错误:枚举成员是只读的
Weekday.Monday = 1; // Error
2. 避免类型不安全的枚举用法
enum Status {
Active = 1,
Inactive = 2
}
// 不好的写法:允许任何数字
function processStatus(status: number) {
// ...
}
// 好的写法:限制为枚举类型
function processStatus(status: Status) {
// ...
}
3. 注意枚举的大小
// 避免创建过大的枚举
enum LargeEnum {
Value1, Value2, Value3, // ... 数百个值
}
// 考虑使用常量对象
const Constants = {
Value1: 0,
Value2: 1,
Value3: 2,
} as const;
总结
- 枚举的优点:
- 提供类型安全
- 改善代码可读性
- 自动编号功能
- 支持反向映射
- 使用场景:
- 状态管理
- API 状态码
- 配置选项
- 权限控制
- 最佳实践:
- 优先使用常量枚举
- 合理选择字符串或数字枚举
- 避免魔法字符串
- 保持枚举简洁
大白话:限制你输入的值值只能是那几种