Angular中如何将JSON返回的字符串映射为TypeScript枚举类型
TypeScript 静态类型检查时,导入的JSON文件字段会被默认推导为string类型,与OrderModel中定义的Status枚举类型不兼容,直接赋值就会抛出 Type 'string' is not assignable to type 'Status' 错误。另外需要注意:直接把普通JSON对象赋值给Class类型的变量,不会生成对应的类实例,只是结构相似的 plain object。
根据实际业务场景选以下任意一种即可:
1. 显式遍历映射(最稳妥,推荐生产环境用)
遍历JSON数组,逐字段赋值生成真正的OrderModel实例,同时完成字符串到枚举的转换,还可以加容错逻辑处理非法值。
修改后的OrderService代码如下:
import { OrderModel } from '../../models/order.model'; import { Status } from "../enums/status.enum"; import orderData from '../json/order.json'; @Injectable({ providedIn: 'root' }) export class OrderService{ orderModel: OrderModel[] = []; constructor() { this.orderModel = orderData.map(item => { const instance = new OrderModel(); instance.id = item.id; instance.notification = item.notification; instance.action = item.action; // 字符串转枚举:匹配枚举键值 const enumKey = item.status.toUpperCase() as keyof typeof Status; instance.status = Status[enumKey]; // 可选:加兜底容错,遇到非法枚举值返回默认值 // if (!Object.values(Status).includes(instance.status)) { // instance.status = Status.LOW; // } // 如果后端返回值大小写不固定,可以用自定义映射表替代上面的转换逻辑 // const statusMap: Record<string, Status> = { // 'high': Status.HIGH, // 'High': Status.HIGH, // 'medium': Status.MEDIUM, // 'Medium': Status.MEDIUM, // 'low': Status.LOW, // 'Low': Status.LOW // } // instance.status = statusMap[item.status] ?? Status.LOW; return instance; }); } getOrderStatus() { console.log(this.orderModel) } }
转换逻辑说明:当前定义的Status是字符串枚举,枚举键为全大写的HIGH/MEDIUM/LOW,对应值为首字母大写的"High"/"Medium"/"Low",和JSON返回的字符串完全匹配,把JSON中的status值转大写后作为键取枚举值,就能得到正确的枚举成员。
2. 类型断言(适合确定返回值100%匹配枚举的场景)
如果不需要生成OrderModel类实例(即OrderModel仅做类型约束,没有定义类方法),且能保证后端返回的status值永远和枚举值一致,可以直接用类型断言跳过TS检查,写法最简洁:
orderModel: OrderModel[] = orderData as OrderModel[];
注意:该方式仅在静态类型层面骗过TS检查,运行时不会做任何类型转换、校验,也不会生成类实例,后续如果类新增方法,调用时会直接报错。
3. 新增JSON类型声明(适配多场景复用)
在项目全局类型声明文件(一般是src/typings.d.ts,没有则新建)中,给导入的order.json添加明确的类型定义,指定status字段为Status类型,之后所有地方导入该JSON文件都不会报类型错误:
declare module '*/order.json' { import { Status } from "../enums/status.enum"; const data: Array<{ id: number; notification: string; action: string; status: Status; }>; export default data; }
该方式和类型断言一样,仅做静态类型约束,没有运行时转换逻辑。
- 生产环境、需要类实例、需要做字段容错的场景,选第一种显式映射方案,鲁棒性最高
- 内部项目、接口返回值完全可控、仅做类型约束的场景,可以选类型断言或者JSON类型声明方案,代码更简洁
内容的提问来源于stack exchange,提问作者C.Das

