TypeScript枚举 #
一、枚举基础 #
1.1 什么是枚举 #
枚举(Enum)是TypeScript的一种特殊类型,用于定义一组命名的常量。枚举使代码更易读、更易维护。
typescript
enum Direction {
Up,
Down,
Left,
Right
}
let dir: Direction = Direction.Up;
console.log(dir);
1.2 枚举的作用 #
- 为一组相关值提供友好的名称
- 提高代码可读性
- 避免使用"魔法数字"
- 提供类型安全
二、数字枚举 #
2.1 基本数字枚举 #
数字枚举的值默认从0开始递增:
typescript
enum Direction {
Up,
Down,
Left,
Right
}
console.log(Direction.Up);
console.log(Direction.Down);
console.log(Direction.Left);
console.log(Direction.Right);
2.2 自定义数值 #
typescript
enum Direction {
Up = 1,
Down,
Left,
Right
}
console.log(Direction.Up);
console.log(Direction.Down);
console.log(Direction.Left);
console.log(Direction.Right);
2.3 全部自定义 #
typescript
enum Direction {
Up = 1,
Down = 2,
Left = 5,
Right = 10
}
console.log(Direction.Up);
console.log(Direction.Down);
console.log(Direction.Left);
console.log(Direction.Right);
2.4 使用表达式 #
typescript
enum FileAccess {
None = 0,
Read = 1 << 0,
Write = 1 << 1,
ReadWrite = Read | Write,
All = ~None
}
console.log(FileAccess.Read);
console.log(FileAccess.Write);
console.log(FileAccess.ReadWrite);
2.5 反向映射 #
数字枚举支持反向映射,可以通过值获取名称:
typescript
enum Direction {
Up,
Down,
Left,
Right
}
console.log(Direction.Up);
console.log(Direction[0]);
console.log(Direction[Direction.Up]);
编译后的JavaScript:
javascript
var Direction;
(function (Direction) {
Direction[Direction["Up"] = 0] = "Up";
Direction[Direction["Down"] = 1] = "Down";
Direction[Direction["Left"] = 2] = "Left";
Direction[Direction["Right"] = 3] = "Right";
})(Direction || (Direction = {}));
三、字符串枚举 #
3.1 基本字符串枚举 #
字符串枚举的每个成员都需要显式初始化:
typescript
enum Direction {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}
console.log(Direction.Up);
console.log(Direction.Down);
3.2 字符串枚举特点 #
- 没有自增行为
- 不支持反向映射
- 更好的可读性
typescript
enum HttpStatus {
OK = '200 OK',
NotFound = '404 Not Found',
ServerError = '500 Internal Server Error'
}
function handleResponse(status: HttpStatus): void {
console.log(`Response: ${status}`);
}
handleResponse(HttpStatus.OK);
3.3 实际应用 #
typescript
enum Environment {
Development = 'development',
Staging = 'staging',
Production = 'production'
}
const config = {
[Environment.Development]: {
apiUrl: 'http://localhost:3000'
},
[Environment.Staging]: {
apiUrl: 'https://staging.example.com'
},
[Environment.Production]: {
apiUrl: 'https://api.example.com'
}
};
const env = Environment.Development;
console.log(config[env].apiUrl);
四、异构枚举 #
4.1 什么是异构枚举 #
异构枚举混合了数字和字符串成员:
typescript
enum BooleanEnum {
No = 0,
Yes = 'YES'
}
console.log(BooleanEnum.No);
console.log(BooleanEnum.Yes);
4.2 不推荐使用 #
异构枚举容易造成混淆,通常不推荐使用:
typescript
enum BadPractice {
A = 0,
B = 'hello',
C = 1,
D = 'world'
}
五、const枚举 #
5.1 什么是const枚举 #
const枚举在编译时会被内联,不会生成额外的JavaScript代码:
typescript
const enum Direction {
Up,
Down,
Left,
Right
}
let dir = Direction.Up;
编译后:
javascript
var dir = 0;
5.2 const枚举的优势 #
- 更小的输出代码
- 更好的性能
- 没有运行时开销
5.3 使用场景 #
typescript
const enum HttpStatusCode {
OK = 200,
NotFound = 404,
ServerError = 500
}
function handleStatus(code: HttpStatusCode): string {
switch (code) {
case HttpStatusCode.OK:
return 'Success';
case HttpStatusCode.NotFound:
return 'Not Found';
case HttpStatusCode.ServerError:
return 'Server Error';
}
}
5.4 preserveConstEnums选项 #
设置preserveConstEnums为true时,会保留枚举对象:
typescript
const enum Direction {
Up,
Down
}
编译后:
javascript
var Direction;
(function (Direction) {
Direction[Direction["Up"] = 0] = "Up";
Direction[Direction["Down"] = 1] = "Down";
})(Direction || (Direction = {}));
六、枚举成员 #
6.1 常量成员 #
常量成员在编译时就能确定值:
typescript
enum E {
A = 0,
B = 1 << 0,
C = 1 + 2,
D = A + B
}
6.2 计算成员 #
计算成员在运行时才能确定值:
typescript
enum E {
A = Math.random(),
B = 'hello'.length,
C = Date.now()
}
6.3 成员类型 #
typescript
enum E {
A,
B = 1,
C = 'hello'
}
type A = E.A;
type B = E.B;
type C = E.C;
let a: E.A = E.A;
let b: E.B = E.B;
七、联合枚举类型 #
7.1 枚举作为联合类型 #
typescript
enum Status {
Pending,
Approved,
Rejected
}
function handleStatus(status: Status): void {
console.log(`Status: ${status}`);
}
handleStatus(Status.Pending);
handleStatus(0);
handleStatus(100);
7.2 枚举成员作为类型 #
typescript
enum ShapeKind {
Circle,
Square,
Triangle
}
interface Circle {
kind: ShapeKind.Circle;
radius: number;
}
interface Square {
kind: ShapeKind.Square;
sideLength: number;
}
let circle: Circle = {
kind: ShapeKind.Circle,
radius: 10
};
circle.kind = ShapeKind.Square;
八、运行时枚举 #
8.1 枚举是真实对象 #
枚举在运行时是真实存在的对象:
typescript
enum E {
A, B, C
}
function f(obj: { A: number }): void {
console.log(obj.A);
}
f(E);
8.2 遍历枚举 #
typescript
enum Color {
Red = 'RED',
Green = 'GREEN',
Blue = 'BLUE'
}
for (const key in Color) {
console.log(key);
}
Object.keys(Color).forEach(key => {
console.log(`${key}: ${Color[key as keyof typeof Color]}`);
});
8.3 获取枚举值列表 #
typescript
enum Direction {
Up = 1,
Down = 2,
Left = 3,
Right = 4
}
const values = Object.values(Direction).filter(v => typeof v === 'number') as Direction[];
console.log(values);
const keys = Object.keys(Direction).filter(k => isNaN(Number(k)));
console.log(keys);
九、枚举与类型安全 #
9.1 类型安全的枚举参数 #
typescript
enum UserRole {
Admin = 'ADMIN',
User = 'USER',
Guest = 'GUEST'
}
function checkPermission(role: UserRole): boolean {
return role === UserRole.Admin;
}
checkPermission(UserRole.Admin);
checkPermission('ADMIN');
9.2 字符串枚举的类型安全 #
typescript
enum Status {
Active = 'ACTIVE',
Inactive = 'INACTIVE'
}
function setStatus(status: Status): void {
console.log(`Status set to: ${status}`);
}
setStatus(Status.Active);
setStatus('ACTIVE');
十、枚举最佳实践 #
10.1 使用const枚举优化性能 #
typescript
const enum Priority {
Low = 1,
Medium = 2,
High = 3
}
function process(priority: Priority): void {
console.log(`Processing with priority: ${priority}`);
}
process(Priority.High);
10.2 使用字符串枚举提高可读性 #
typescript
enum LogLevel {
Debug = 'DEBUG',
Info = 'INFO',
Warn = 'WARN',
Error = 'ERROR'
}
function log(level: LogLevel, message: string): void {
console.log(`[${level}] ${message}`);
}
log(LogLevel.Info, 'Application started');
10.3 避免异构枚举 #
typescript
enum Bad {
A = 0,
B = 'hello'
}
enum Good {
A = 'A',
B = 'B'
}
10.4 使用枚举代替魔法数字 #
typescript
function process(status: number): void {
if (status === 0) {
console.log('Pending');
} else if (status === 1) {
console.log('Approved');
}
}
enum Status {
Pending = 0,
Approved = 1,
Rejected = 2
}
function processBetter(status: Status): void {
if (status === Status.Pending) {
console.log('Pending');
} else if (status === Status.Approved) {
console.log('Approved');
}
}
十一、枚举替代方案 #
11.1 使用联合类型 #
typescript
type Direction = 'up' | 'down' | 'left' | 'right';
function move(dir: Direction): void {
console.log(`Moving ${dir}`);
}
move('up');
11.2 使用对象常量 #
typescript
const Direction = {
Up: 'UP',
Down: 'DOWN',
Left: 'LEFT',
Right: 'RIGHT'
} as const;
type Direction = typeof Direction[keyof typeof Direction];
function move(dir: Direction): void {
console.log(`Moving ${dir}`);
}
move(Direction.Up);
11.3 选择建议 #
| 场景 | 推荐方案 |
|---|---|
| 需要反向映射 | 数字枚举 |
| 需要更好的可读性 | 字符串枚举 |
| 需要最小化代码 | const枚举 |
| 简单的值集合 | 联合类型 |
| 需要运行时遍历 | 普通枚举或对象常量 |
十二、总结 #
本章介绍了TypeScript枚举类型:
枚举类型 #
- 数字枚举:默认从0递增,支持反向映射
- 字符串枚举:需要显式初始化,不支持反向映射
- 异构枚举:混合数字和字符串,不推荐使用
- const枚举:编译时内联,性能最优
最佳实践 #
- 使用const枚举优化性能
- 使用字符串枚举提高可读性
- 避免异构枚举
- 使用枚举代替魔法数字
- 根据场景选择枚举或联合类型
最后更新:2026-03-26