如何在TypeScript中将导入JSON的字符串属性映射为枚举类型
问题描述
假设我有如下JSON数据:
[ { "type": "one", "tile": { "x": 0, "y": 0 }}, { "type": "two", "tile": null } ]
将其导入TypeScript模块:
import dataJson from "data.json";
若定义类型type T = typeof dataJson;,则T会被推断为:
type T = ({ type: string; tile: { x: number; y: number; }; } | { type: string; tile: null; })[]
但我期望将其类型定义为:
enum Type { one, two } interface Entry { type: Type, tile: { x: number, y: number } | null } const data: Entry[] = dataJson;
此时TypeScript会报错:
Types of property 'type' are incompatible.
Type 'string' is not assignable to type 'FeatureType'. ts(2322)
我清楚报错原因,但不知如何解决,请问能否将自动生成的typeof dataJson类型转换为Entry类型?
解决方案
方法1:直接使用类型断言
如果能确定JSON数据完全符合Entry结构,直接用类型断言告诉TypeScript数据的真实类型:
// 基础断言 const data = dataJson as Entry[]; // 更严格的双重断言(当基础断言不生效时使用) const data = dataJson as unknown as Entry[];
方法2:添加运行时类型守卫校验
如果需要确保数据合法性,写一个类型守卫函数,在运行时验证每个条目是否符合Entry规范,同时让TypeScript认可类型转换:
function isEntry(item: unknown): item is Entry { if (typeof item !== 'object' || item === null) return false; const entry = item as Entry; // 验证type是否属于Type枚举的有效值,同时校验tile的结构 return Object.values(Type).includes(entry.type as Type) && ( entry.tile === null || (typeof entry.tile === 'object' && typeof (entry.tile as any).x === 'number' && typeof (entry.tile as any).y === 'number') ); } // 过滤合法数据并转换类型 const data = dataJson.filter(isEntry) as Entry[];
方法3:让TypeScript推断更精确的JSON类型
修改JSON导入方式,让TS把JSON中的字符串推断为字面量类型而非宽泛的string(需要TypeScript 5.0+):
首先确保tsconfig.json中开启resolveJsonModule和esModuleInterop,然后导入时添加类型断言:
import dataJson from "./data.json" assert { type: "json" };
同时将枚举改为字符串枚举,和JSON中的值匹配:
enum Type { one = "one", two = "two" } interface Entry { type: Type; tile: { x: number; y: number } | null; } // 此时TS可自动匹配类型,无需额外断言 const data: Entry[] = dataJson;
方法4:基于原有推断类型做映射转换
如果不想修改枚举或导入方式,可以基于typeof dataJson定义转换后的类型:
type InferEntry = typeof dataJson[number] & { type: Type; }; const data = dataJson as InferEntry[];
内容的提问来源于stack exchange,提问作者NathanAldenSr
相关产品推荐
相关产品推荐

