TypeScript 状态映射实战:从枚举到多语言的最佳实践
在前后端分离的开发模式中,后端接口常通过数字或字符串形式的枚举值(如 0、1、"draft")表示业务状态、类型等信息。而前端不仅需要将这些值转换为用户友好的文本(如中文“草稿”、英文“Draft”),还需考虑多语言切换、状态合法性校验等问题。本文将深入探讨 5 种常见的状态映射方案,从最基础的枚举反向映射到面向企业的 Class 封装,分析其适用场景、类型安全性和扩展能力。
一. 直接根据值渲染
<template>
<div class="content">
<!-- 直接根据 valueFromBackend 显示状态 -->
<span v-if="valueFromBackend === StatusMap.DRAFT">未确认</span>
<span v-else-if="valueFromBackend === StatusMap.PUBLISHED">已发布</span>
<span v-else-if="valueFromBackend === StatusMap.DELETED">已删除</span>
<span v-else>未知状态</span>
</div>
</template>
<script setup lang="ts">
//用原生js定义
const StatusMap = {
DRAFT: 0,
PUBLISHED: 1,
DELETED: 2
};
//使用ts定义
export enum Status {
DRAFT = 0,
PUBLISHED = 1,
DELETED= 2
}
const valueFromBackend = 0; // 假设后端返回 0
</script>
优点
- 简单快捷:无需额外定义映射对象,直接利用 TypeScript 枚举的反向映射特性。
- 代码量少:适合快速原型开发或简单状态判断。
缺点
- 强耦合枚举键名:模板中硬编码枚举键名(如
'Unconfirmed'),键名修改后需全局替换。 - 无法处理非法值:若
row.type为非法值(如3),Status[3]返回undefined,但无错误提示。 - 不支持多语言:文本直接写在模板中,难以扩展国际化。
- 类型不安全:反向映射的返回值类型为
string | undefined,需手动处理。
适用场景
- 临时调试或小型项目,无需长期维护。
- 状态值稳定且无需国际化。
二. 数组遍历写法
<template>
<ul>
<li v-for="status in statusList" :key="status.value">
<template v-if="valueFromBackend === status.value">
{{ status.label }}
</template>
</li>
</ul>
</template>
<script setup>
const statusList = [
{ value: 0, label: '未确认' },
{ value: 1, label: '已确认' }
];
const valueFromBackend = 0;
</script>
优点
- 结构清晰:状态值与文本集中管理,便于扩展新状态。
- 动态渲染:适合需要遍历所有状态并高亮当前值的场景(如状态筛选菜单)。
缺点
- 性能开销:每次渲染需遍历整个数组,状态较多时可能影响性能。
- 逻辑重复:状态判断逻辑分散在模板中,可能产生冗余代码。
- 类型松散:未使用 TypeScript 约束,可能因拼写错误导致运行时问题。
适用场景
- 需要动态生成状态列表的界面(如筛选器、选项卡)。
- 状态数量较少且变化频繁。
三. 枚举 + 映射对象写法
<template>
<div class="content">
<span>{{ StatusChinese[valueFromBackend as Status] }}</span>
</div>
</template>
<script setup lang="ts">
enum Status {
Unconfirmed = 0,
Confirmed = 1,
}
const StatusChinese = {
[Status.Unconfirmed]: '未确认',
[Status.Confirmed]: '已确认',
} as const;
const StatusEnglish = {
[Status.Unconfirmed]: 'unconfirmed',
[Status.Confirmed]: 'Confirmed',
} as const;
// 获取中文
console.log(StatusChinese[backendValue]); // 输出 "草稿"
// 获取英文
console.log(StatusEnglish[backendValue]); // 输出 "Draft"
const valueFromBackend = 0; // 假设后端返回 0
</script>
优点
- 类型安全:通过
as Status和as const确保类型正确,编译时检查非法值。 - 解耦键名与文本:修改枚举键名不影响显示逻辑,只需更新映射对象。
- 扩展性强:轻松支持多语言(替换映射对象即可)。
- 集中维护:状态文本统一管理,避免硬编码。
缺点
- 代码量略多:需定义枚举和映射对象,小型项目可能显得冗余。
- 学习成本:需熟悉 TypeScript 高级特性(如
as const和类型守卫)。
适用场景
- 中大型项目或长期维护的代码库。
- 需要国际化、主题切换等扩展功能。
四.Class 封装
class OrderStatus { // 定义枚举值 static readonly Draft = 0; static readonly Published = 1; static readonly Deleted = 2; // 私有映射表 private static zhMap = { [OrderStatus.Draft]: "草稿", [OrderStatus.Published]: "已发布", [OrderStatus.Deleted]: "已删除", } as const; // 获取中文 static getChinese(value: number): string { return this.zhMap[value as keyof typeof this.zhMap] || "未知状态"; } // 校验合法性 static isValid(value: number): boolean { return Object.values(OrderStatus).includes(value); } } // 使用示例 console.log(OrderStatus.getChinese(0)); // "草稿"
优点
- 逻辑高度集中:状态值、映射关系、校验方法全部封装在类中。
- 强封装性:私有映射表 (
zhMap) 避免外部误修改。 - 易于扩展:可添加更多方法(如多语言、日志记录)。
- 类型安全:静态方法配合
keyof实现安全访问。
缺点
- 代码冗余:简单场景下显得过于繁琐。
- 过度设计:小型项目可能不需要完整的面向对象结构。
- 初始化成本:需实例化或静态调用,略失灵活性。
适用场景
- 复杂状态逻辑(如状态机、流程审批)。
- 需要集中管理校验、转换、日志等附加功能。
- 团队熟悉面向对象设计模式。
五.联合类型 + 对象映射
// 定义联合类型 type StatusValue = 0 | 1 | 2; // 定义映射对象 const StatusMap = { 0: { en: "Draft", zh: "草稿" }, 1: { en: "Published", zh: "已发布" }, 2: { en: "Deleted", zh: "已删除" }, } as const; // 类型安全访问函数 const getStatusText = (value: StatusValue) => { return StatusMap[value] || { en: "Unknown", zh: "未知状态" }; }; // 使用示例 console.log(getStatusText(0).zh); // "草稿"
优点
- 极简轻量:无需定义枚举或类,直接通过对象和类型约束。
- 灵活直观:对象字面量清晰表达键值关系。
- 类型精确:联合类型
StatusValue严格限制取值范围。 - 无额外抽象:适合快速开发或简单状态管理。
缺点
- 维护成本高:新增状态需修改联合类型和映射对象。
- 无法动态扩展:联合类型需静态定义所有可能值。
- 复用性差:逻辑分散,不适合跨组件复用。
适用场景
- 状态数量固定且极少变化的场景。
- 轻量级工具函数或临时模块。
- 开发者偏好函数式编程风格。
六.总结
1. 简单场景
- 推荐方案:初级写法(反向映射)或数组遍历写法
- 理由:快速实现,代码量少,适合临时需求或状态极少变化的场景。
2. 企业级项目
- 推荐方案:枚举 + 映射对象 或 Class 封装
- 理由:类型安全、解耦键名与文本,长期维护成本低,适合中大型项目。
3. 动态列表需求
- 推荐方案:数组遍历写法
- 理由:直接遍历状态列表,灵活渲染 UI(如筛选菜单、选项卡)。
4. 国际化/多主题
- 推荐方案:枚举 + 映射对象 + 语言包(如
i18n) - 理由:集中管理多语言文本,轻松扩展新语言,与国际化库无缝集成。

浙公网安备 33010602011771号