TypeScript中的枚举
在TypeScript中,枚举(Enum) 是一种用于定义命名常量集合的类型,它可以帮助开发者组织和表示一组相关的固定值(如状态、选项、类型等)。与JavaScript相比,TypeScript的枚举提供了更强的类型约束和可读性;与Java枚举相比,TypeScript枚举更灵活,支持数值、字符串等多种类型。
一、基本定义与语法
使用 enum
关键字定义枚举,语法如下:
enum 枚举名 {成员1,成员2,...成员n
}
示例:最简单的枚举
// 定义一个表示方向的枚举
enum Direction {Up, // 成员1Down, // 成员2Left, // 成员3Right // 成员4
}
二、枚举的类型
TypeScript 枚举主要分为数值枚举、字符串枚举和异构枚举(混合类型),其中前两种最常用。
1. 数值枚举(Numeric Enums)
数值枚举的成员会被赋值为数字,默认从 0
开始递增。也可以手动指定成员的值,后续成员会基于前一个值自动递增。
示例1:默认自动赋值
enum Direction {Up, // 默认为 0Down, // 自动递增为 1Left, // 自动递增为 2Right // 自动递增为 3
}console.log(Direction.Up); // 输出:0
console.log(Direction.Right); // 输出:3
示例2:手动指定初始值
enum Status {Pending = 1, // 手动指定为 1Success, // 自动递增为 2Failed // 自动递增为 3
}console.log(Status.Pending); // 输出:1
console.log(Status.Success); // 输出:2
示例3:完全手动赋值(可非连续)
enum Priority {Low = 10,Medium = 20,High = 50 // 无需连续
}console.log(Priority.Medium); // 输出:20
2. 字符串枚举(String Enums)
字符串枚举的每个成员必须用字符串字面量或另一个字符串枚举成员赋值,没有“自动递增”行为。字符串枚举的优势是序列化时更清晰(数值可能无意义,字符串更易读)。
示例:
enum Message {Success = "操作成功",Error = "操作失败",Loading = "加载中"
}console.log(Message.Success); // 输出:"操作成功"// 也可以引用其他字符串枚举成员
enum HttpStatus {Ok = Message.Success,BadRequest = "请求错误"
}
console.log(HttpStatus.Ok); // 输出:"操作成功"
3. 异构枚举(Heterogeneous Enums)
混合数值和字符串成员的枚举,称为异构枚举。不推荐使用,因为容易造成混淆,但TypeScript语法上允许。
enum MixedEnum {No = 0,Yes = "YES"
}
三、枚举的核心特性
1. 反向映射(仅数值枚举支持)
数值枚举会生成双向映射:从“成员名”到“值”,以及从“值”到“成员名”。这是TypeScript枚举的独特特性。
enum Direction {Up, // 0Down // 1
}// 正向映射:成员名 -> 值
console.log(Direction.Up); // 0// 反向映射:值 -> 成员名
console.log(Direction[0]); // "Up"
console.log(Direction[1]); // "Down"
注意:字符串枚举不支持反向映射,因为编译后不会生成值到名的映射。
2. 枚举成员的类型
枚举成员可以作为类型使用,用于约束变量只能取枚举中的值。
enum Direction {Up,Down
}// 声明变量类型为 Direction 枚举成员
let move: Direction.Up;move = Direction.Up; // 正确
move = Direction.Down; // 错误:Type 'Direction.Down' is not assignable to type 'Direction.Up'
3. 常量枚举(Const Enums)
使用 const enum
定义常量枚举,编译时会被直接替换为对应的值(而非生成对象),可减少运行时代码体积,提升性能。
示例:
// 定义常量枚举
const enum Size {Small = 1,Medium = 2,Large = 3
}// 使用
let s = Size.Medium;
编译后的JavaScript代码(直接替换为值):
let s = 2; // 而非 Size.Medium
注意:常量枚举不能包含计算成员(见下文)。
4. 计算成员
枚举成员的值可以是计算表达式(如算术运算、函数调用等),但需注意:
- 计算成员后的成员必须手动赋值(无法自动递增)。
- 常量枚举(
const enum
)不能包含计算成员。
enum CalculateEnum {A = 1 + 2, // 计算表达式(3)B = A * 2, // 引用其他成员(6)C = getValue(), // 函数调用(假设返回10)D = 20 // 计算成员后必须手动赋值
}function getValue() {return 10;
}console.log(CalculateEnum.A); // 3
console.log(CalculateEnum.C); // 10
四、枚举与联合类型的对比
在某些场景下,联合类型可以替代枚举(尤其是字符串枚举),且更灵活。例如:
// 枚举方式
enum Direction {Up = "UP",Down = "DOWN"
}// 联合类型方式(效果类似)
type DirectionUnion = "UP" | "DOWN";
区别:
- 枚举会生成实际的运行时对象,联合类型仅在编译时做类型检查。
- 枚举更适合需要“值集合”且可能在运行时引用的场景;联合类型更轻量,适合简单的字符串/数值约束。
五、使用场景
枚举适合表示固定且相关的常量集合,例如:
- 状态码(成功、失败、加载中)
- 选项(性别、角色、权限)
- 方向/类型(上下左右、用户类型)
// 状态码枚举示例
enum StatusCode {Success = 200,NotFound = 404,ServerError = 500
}// 接口返回类型约束
interface ApiResponse {code: StatusCode;data: any;
}function handleResponse(res: ApiResponse) {if (res.code === StatusCode.Success) {// 处理成功逻辑}
}
总结
TypeScript枚举是组织常量的强大工具,核心特点包括:
- 支持数值枚举(含反向映射)、字符串枚举(更易读)。
- 可通过
const enum
优化性能。 - 成员可作为类型使用,提供严格的类型检查。
根据场景选择枚举或联合类型:需要运行时访问或复杂逻辑时用枚举,简单约束时用联合类型更轻量。