如何基于JSON对象的值创建TypeScript联合类型且避免重复定义
问题
现有用于下拉菜单的JSON结构如下:
[ { "label": "整套房源", "value": "entire_place" }, { "label": "共享房间", "value": "shared_room" }, { "label": "私人房间", "value": "private_room" } ]
其中label是用户可见文本,value是存入数据库的值。需要生成对应的TypeScript联合类型:
type Property = "entire_place" | "private_room" | "shared_room";
如何实现无需重复定义数据?避免新增选项时同时修改JSON对象与类型;若无法实现,有什么更好的存储带标签数据并用于校验的替代方案?
解决方案
方法一:从常量数组自动推导联合类型
TypeScript支持通过as const断言保留字面量类型,以此实现从选项数组自动生成联合类型,只需维护数组一处即可:
- 定义带
as const断言的选项常量:
const propertyOptions = [ { label: "整套房源", value: "entire_place" }, { label: "共享房间", value: "shared_room" }, { label: "私人房间", value: "private_room" }, ] as const;
as const会让TypeScript将数组元素、对象属性都视为不可变的字面量类型,而非宽泛的string。
- 自动推导联合类型:
// 提取数组中每个元素的value属性类型,组成联合类型 type Property = typeof propertyOptions[number]["value"];
此时Property的类型自动等同于"entire_place" | "shared_room" | "private_room",新增或修改选项时,只需调整propertyOptions数组,类型会自动同步更新。
如果选项来自外部JSON文件,需在tsconfig.json中开启resolveJsonModule选项,导入后同样用上述方式推导类型:
import propertyOptions from './property-options.json' assert { type: 'json' }; type Property = typeof propertyOptions[number]["value"];
方法二:用枚举生成选项数组(反向维护)
若场景更强调类型约束,可先定义枚举,再从枚举自动生成下拉菜单选项数组,同样只需维护枚举一处:
- 定义枚举:
enum Property { EntirePlace = "entire_place", SharedRoom = "shared_room", PrivateRoom = "private_room" }
- 生成选项数组:
const propertyOptions = Object.entries(Property).map(([key, value]) => ({ // 将枚举键转换为友好的用户可见标签(如EntirePlace → "Entire Place") label: key.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase()), value: value }));
这种方式适合需要在代码中直接使用枚举值(如接口定义、条件判断)的场景,新增选项时只需修改枚举,选项数组会自动生成。
内容的提问来源于stack exchange,提问作者user19910212
相关产品推荐
相关产品推荐

