枚举(Enum)
概述
枚举是一种特殊的类型,用于定义一组命名的常量值。
数字枚举
基本语法
// 数字枚举(默认从 0 开始)
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right // 3
}
// 使用枚举
let direction: Direction = Direction.Up;
console.log(direction); // 0
console.log(Direction.Up); // 0
console.log(Direction[0]); // 'Up'
自定义起始值
// 自定义起始值
enum StatusCode {
OK = 200,
Created = 201,
BadRequest = 400,
NotFound = 404,
ServerError = 500
}
console.log(StatusCode.OK); // 200
console.log(StatusCode.NotFound); // 404
自动递增
// 后续值会自动递增
enum Status {
Active = 1,
Inactive, // 2
Pending, // 3
Suspended // 4
}
// 混合定义
enum Mixed {
A, // 0
B = 5,
C, // 6
D = 10,
E // 11
}
字符串枚举
基本语法
// 字符串枚举
enum Color {
Red = 'RED',
Green = 'GREEN',
Blue = 'BLUE'
}
let color: Color = Color.Red;
console.log(color); // 'RED'
console.log(Color.Green); // 'GREEN'
// 字符串枚举不能反向映射
// console.log(Color['RED']); // undefined
混合枚举
// 数字和字符串混合枚举
enum Status {
Active = 'ACTIVE',
Inactive = 'INACTIVE',
Pending = 1,
Processing = 2
}
console.log(Status.Active); // 'ACTIVE'
console.log(Status.Pending); // 1
常量枚举
基本语法
// 常量枚举(编译时会被内联)
const enum Direction {
Up,
Down,
Left,
Right
}
let direction: Direction = Direction.Up;
// 编译后:let direction = 0;
常量枚举的优势
// 普通枚举会生成对象
enum RegularEnum {
A,
B,
C
}
// 编译后会生成 IIFE 代码
// 常量枚举直接内联
const enum ConstEnum {
A,
B,
C
}
// 编译后直接使用数字值
// 性能更好
const value = ConstEnum.A; // 编译为:const value = 0;
枚举类型
枚举成员类型
// 每个枚举成员都是独立的类型
enum Status {
Active,
Inactive
}
let status: Status.Active = Status.Active;
// status = Status.Inactive; // 错误
联合枚举类型
// 枚举类型是所有成员的联合
enum Direction {
Up,
Down,
Left,
Right
}
function move(direction: Direction): void {
switch (direction) {
case Direction.Up:
console.log('Moving up');
break;
case Direction.Down:
console.log('Moving down');
break;
// 必须处理所有情况
}
}
实际应用示例
1. HTTP 状态码
enum HttpStatus {
OK = 200,
Created = 201,
NoContent = 204,
BadRequest = 400,
Unauthorized = 401,
Forbidden = 403,
NotFound = 404,
InternalServerError = 500
}
function handleResponse(status: HttpStatus): void {
if (status >= 200 && status < 300) {
console.log('Success');
} else if (status >= 400 && status < 500) {
console.log('Client error');
} else {
console.log('Server error');
}
}
2. 用户角色
enum UserRole {
Admin = 'ADMIN',
Editor = 'EDITOR',
Viewer = 'VIEWER',
Guest = 'GUEST'
}
interface User {
id: number;
name: string;
role: UserRole;
}
function hasPermission(user: User, action: string): boolean {
switch (user.role) {
case UserRole.Admin:
return true;
case UserRole.Editor:
return ['read', 'write', 'edit'].includes(action);
case UserRole.Viewer:
return ['read'].includes(action);
case UserRole.Guest:
return false;
default:
return false;
}
}
3. 订单状态
enum OrderStatus {
Pending = 'PENDING',
Confirmed = 'CONFIRMED',
Shipped = 'SHIPPED',
Delivered = 'DELIVERED',
Cancelled = 'CANCELLED'
}
interface Order {
id: number;
status: OrderStatus;
createdAt: Date;
}
function canCancel(order: Order): boolean {
return [OrderStatus.Pending, OrderStatus.Confirmed].includes(order.status);
}
function canTrack(order: Order): boolean {
return [OrderStatus.Shipped, OrderStatus.Delivered].includes(order.status);
}
4. 环境配置
enum Environment {
Development = 'development',
Staging = 'staging',
Production = 'production'
}
const config = {
[Environment.Development]: {
apiUrl: 'http://localhost:3000',
debug: true
},
[Environment.Staging]: {
apiUrl: 'https://staging-api.example.com',
debug: true
},
[Environment.Production]: {
apiUrl: 'https://api.example.com',
debug: false
}
};
function getConfig(env: Environment) {
return config[env];
}
5. 事件类型
enum EventType {
Click = 'CLICK',
Focus = 'FOCUS',
Blur = 'BLUR',
Submit = 'SUBMIT',
Change = 'CHANGE'
}
type EventHandler = (event: Event) => void;
const handlers: Record<EventType, EventHandler[]> = {
[EventType.Click]: [],
[EventType.Focus]: [],
[EventType.Blur]: [],
[EventType.Submit]: [],
[EventType.Change]: []
};
function addEventListener(type: EventType, handler: EventHandler): void {
handlers[type].push(handler);
}
枚举的替代方案
const 对象
// 使用 const 对象代替枚举
const Direction = {
Up: 0,
Down: 1,
Left: 2,
Right: 3
} as const;
type Direction = typeof Direction[keyof typeof Direction];
let direction: Direction = Direction.Up;
联合类型
// 使用联合类型代替字符串枚举
type Status = 'active' | 'inactive' | 'pending';
function setStatus(status: Status): void {
console.log(status);
}
setStatus('active'); // 正确
// setStatus('unknown'); // 错误
const 断言
// 使用 const 断言创建不可变对象
const ROLES = {
Admin: 'ADMIN',
Editor: 'EDITOR',
Viewer: 'VIEWER'
} as const;
type Role = typeof ROLES[keyof typeof ROLES];
function checkRole(role: Role): boolean {
return role === ROLES.Admin;
}
最佳实践
- 使用字符串枚举:可读性更好
- 使用常量枚举:性能更好
- 避免数字枚举:除非有明确的数字含义
- 考虑 const 对象:更轻量的替代方案
// 好的做法
enum Status {
Active = 'ACTIVE',
Inactive = 'INACTIVE'
}
// 避免
enum Status {
Active, // 0 是什么意思?
Inactive // 1 是什么意思?
}
参考
目录