eagleye

TypeScript 枚举类型:企业级实用指南

# TypeScript 枚举类型:企业级实用指南

## 什么是枚举?

枚举(Enum)是 TypeScript 提供的强大功能,它允许我们为一组相关的**命名常量值**定义一种特殊的数据类型。枚举的核心价值在于:**为数值(或字符串)赋予有意义的名称,使代码更易读、更易维护**。

### 基础定义

```typescript
// 数字枚举
enum OrderStatus {
Pending, // 0
Processing, // 1
Shipped, // 2
Delivered, // 3
Cancelled // 4
}

// 字符串枚举
enum LogLevel {
Debug = "DEBUG",
Info = "INFO",
Warn = "WARN",
Error = "ERROR"
}
```

## 枚举在企业应用中的核心价值

1. **提升代码可读性**
```typescript
// 没有枚举
if (status === 2) { /* ... */ }

// 使用枚举
if (status === OrderStatus.Shipped) { /* ... */ }
```

2. **增强类型安全性**
```typescript
function updateOrder(status: OrderStatus) { /* ... */ }

updateOrder(OrderStatus.Processing); // 正确
updateOrder(5); // 错误:5 不是有效的 OrderStatus
```

3. **简化常量管理**
```typescript
// 替代方案:常量集合
const OrderStatus = {
Pending: 0,
Processing: 1,
// ...
} as const;
```

4. **支持反向映射**
```typescript
console.log(OrderStatus[2]); // 输出 "Shipped"
```

## 企业级枚举实用模式

### 1. 业务状态管理

```typescript
// 订单状态枚举
enum OrderStatus {
Draft = 10, // 草稿
Submitted = 20, // 已提交
Approved = 30, // 已批准
Shipped = 40, // 已发货
Delivered = 50, // 已交付
Cancelled = 90, // 已取消
Refunded = 100 // 已退款
}

// 使用示例
function handleOrderStatusChange(newStatus: OrderStatus) {
switch (newStatus) {
case OrderStatus.Submitted:
// 处理提交逻辑
break;
case OrderStatus.Shipped:
// 处理发货逻辑
break;
// ...
}
}

// 类型安全的状态检查
if (currentStatus >= OrderStatus.Shipped) {
console.log("订单已在运输途中");
}
```

### 2. API 错误码管理

```typescript
// 错误码枚举
enum ApiErrorCode {
// 认证错误 (1000-1999)
Unauthorized = 1001,
InvalidToken = 1002,
ExpiredToken = 1003,

// 验证错误 (2000-2999)
ValidationError = 2001,
MissingRequiredField = 2002,

// 业务逻辑错误 (3000-3999)
InsufficientFunds = 3001,
ItemOutOfStock = 3002,

// 系统错误 (5000-5999)
DatabaseError = 5001,
ExternalServiceError = 5002
}

// 错误处理函数
function handleApiError(errorCode: ApiErrorCode) {
if (errorCode >= 5000) {
// 系统级错误
logSystemError(errorCode);
}

// 获取错误信息
const errorMessage = ErrorMessages[errorCode] || "未知错误";
showUserAlert(errorMessage);
}

// 错误信息映射
const ErrorMessages: Record<ApiErrorCode, string> = {
[ApiErrorCode.Unauthorized]: "未授权访问",
[ApiErrorCode.InvalidToken]: "无效的认证令牌",
[ApiErrorCode.ExpiredToken]: "认证令牌已过期",
// ...
};
```

### 3. 权限管理

```typescript
// 权限标志枚举 (位标志)
enum PermissionFlags {
None = 0, // 0b0000
Read = 1 << 0, // 0b0001
Write = 1 << 1, // 0b0010
Delete = 1 << 2, // 0b0100
Admin = 1 << 3, // 0b1000

// 组合权限
ReadWrite = Read | Write, // 0b0011
FullControl = Read | Write | Delete | Admin // 0b1111
}

// 用户权限检查
function checkPermission(userPermissions: PermissionFlags, required: PermissionFlags): boolean {
return (userPermissions & required) === required;
}

// 使用示例
const userPermissions = PermissionFlags.Read | PermissionFlags.Write;

console.log(checkPermission(userPermissions, PermissionFlags.Read)); // true
console.log(checkPermission(userPermissions, PermissionFlags.Delete)); // false
console.log(checkPermission(userPermissions, PermissionFlags.ReadWrite)); // true
```

### 4. 多语言支持

```typescript
enum Locale {
EN_US = "en-US",
ZH_CN = "zh-CN",
JA_JP = "ja-JP",
KO_KR = "ko-KR",
FR_FR = "fr-FR"
}

// 资源映射
const Resources: Record<Locale, Record<string, string>> = {
[Locale.EN_US]: {
welcome: "Welcome!",
goodbye: "Goodbye!"
},
[Locale.ZH_CN]: {
welcome: "欢迎!",
goodbye: "再见!"
},
// ...
};

// 国际化函数
function t(key: string, locale: Locale = Locale.EN_US): string {
return Resources[locale][key] || key;
}

// 使用示例
console.log(t("welcome", Locale.ZH_CN)); // 输出: "欢迎!"
```

## 高级枚举技巧

### 常量枚举 (性能优化)

```typescript
// 使用 const enum 进行优化 (编译时内联)
const enum HttpMethod {
GET = "GET",
POST = "POST",
PUT = "PUT",
DELETE = "DELETE",
PATCH = "PATCH"
}

// 编译后会被替换为字面量
const method = HttpMethod.GET; // 编译后: const method = "GET"
```

### 枚举与联合类型结合

```typescript
// 枚举定义
enum LogLevel {
Debug = "DEBUG",
Info = "INFO",
Warn = "WARN",
Error = "ERROR"
}

// 基于枚举的联合类型
type LogLevelType = `${LogLevel}`;

// 使用联合类型作为参数
function log(message: string, level: LogLevelType) {
console.log(`[${level}] ${message}`);
}

log("Starting application", LogLevel.Info); // 正确
log("Critical error", "ERROR"); // 正确
log("Warning", "WARNING"); // 错误: "WARNING" 不是有效的 LogLevelType
```

### 运行时枚举验证

```typescript
// 枚举值验证函数
function isValidOrderStatus(value: number): value is OrderStatus {
return Object.values(OrderStatus).includes(value);
}

// 使用示例
const inputStatus: number = 30; // 来自API或其他来源

if (isValidOrderStatus(inputStatus)) {
// 类型安全地使用
updateOrderStatus(inputStatus);
} else {
throw new Error(`无效的订单状态: ${inputStatus}`);
}
```

## 企业级最佳实践

1. **命名规范**
- 使用 PascalCase 命名枚举
- 使用有意义的名称(避免通用名称如 `Status`)
- 添加前缀区分(如 `OrderStatus` 而非 `Status`)

2. **值分配策略**
```typescript
// 推荐:显式赋值(避免隐式数值)
enum UserRole {
Guest = 0, // 明确赋值
User = 10, // 预留扩展空间
Moderator = 20,
Admin = 30
}

// 避免:隐式数值(易出错)
enum BadExample {
First, // 0
Second, // 1 - 如果插入新值会破坏顺序
}
```

3. **文档化枚举**
```typescript
/**
* 订单处理状态
*
* - Draft: 订单创建但未提交
* - Submitted: 订单已提交等待处理
* - Processing: 订单正在处理中
* - Shipped: 订单已发货
* - Delivered: 订单已交付
* - Cancelled: 订单已取消
*/
enum OrderStatus {
Draft = 10,
Submitted = 20,
Processing = 30,
Shipped = 40,
Delivered = 50,
Cancelled = 90
}
```

4. **枚举 vs 字面量联合类型**
```typescript
// 枚举适合:有逻辑分组、需要反向映射、有数值关联
enum OrderStatus { /* ... */ }

// 字面量联合类型适合:简单选项、不需要逻辑
type PaymentMethod = 'credit_card' | 'paypal' | 'bank_transfer';
```

5. **避免枚举陷阱**
- 避免超大枚举(考虑改用对象常量)
- 避免字符串和数字混合枚举
- 避免修改已发布的枚举(向后兼容)

## 枚举性能优化

1. **常量枚举用于高频访问**
```typescript
const enum Priority {
Low = 1,
Medium = 2,
High = 3
}
```

2. **对象常量替代大型枚举**
```typescript
// 大型枚举(不推荐)
// enum CountryCode { AF = 'AF', AL = 'AL', ... }

// 替代方案:对象常量 + 类型
const CountryCodes = {
AF: 'Afghanistan',
AL: 'Albania',
// ... 200+ 国家
} as const;

type CountryCode = keyof typeof CountryCodes;
```

## 枚举与后端集成

### 1. DTO 中使用枚举

```typescript
// 前后端共享的枚举定义
export enum UserStatus {
Active = 'ACTIVE',
Inactive = 'INACTIVE',
Suspended = 'SUSPENDED'
}

// DTO 接口
interface UserDto {
id: number;
name: string;
status: UserStatus;
}

// API 响应处理
async function fetchUser(id: number): Promise<UserDto> {
const response = await axios.get(`/api/users/${id}`);
return response.data;
}
```

### 2. 枚举序列化/反序列化

```typescript
// 自定义序列化
class Order {
status: OrderStatus;

toJSON() {
return {
status: OrderStatus[this.status] // 输出字符串
};
}
}

// 自定义反序列化
function parseOrder(data: any): Order {
const order = new Order();
order.status = OrderStatus[data.status as keyof typeof OrderStatus];
return order;
}
```

## 总结:何时使用枚举

| 场景 | 推荐方案 |
|------|---------|
| **固定集合的状态值** | ✅ 枚举 |
| **需要反向映射的值** | ✅ 枚举 |
| **位标志权限系统** | ✅ 枚举 |
| **简单的选项集合** | ⚠️ 字面量联合类型 |
| **大型静态数据集** | ⚠️ 对象常量 + 类型 |
| **需要动态修改的值** | ❌ 避免枚举 |

枚举是 TypeScript 强大的工具,当正确使用时,可以显著提升代码的**可读性、可维护性和类型安全性**。在企业级应用中,合理使用枚举管理状态、错误码和配置值,将使你的代码更加健壮和易于理解。

posted on 2025-08-03 12:55  GoGrid  阅读(16)  评论(0)    收藏  举报

导航