基于外部枚举值定义内部对象键的Zod类型解析问题
基于外部枚举值定义内部对象键的Zod类型解析问题
嘿,我看你在纠结用Zod解析API返回数据的问题——想用自定义枚举约束外层对象的键,同时每个键对应的内部对象还要有和外层键关联的{key}-action属性对吧?我来给你一步步讲怎么实现:
首先先明确你的场景:
API返回的数据格式是这样的:
{ "title": { "title-action": "some value", ...rest }, "body": { "body-action": "some value", ...rest } }
你提到的Zod枚举应该是要补全成这样:
const MyEnum = z.enum(["title", "body"]);
解决方案一:动态生成严格匹配的Schema
这个方法能精准对应枚举里的每个键,同时让内部对象的{key}-action键和外层键自动关联,类型提示也更友好:
// 先提取枚举的字面量类型,方便后续复用 type MyEnumType = z.infer<typeof MyEnum>; // 写个小函数,根据枚举键动态生成对应内部对象的Schema const createInnerSchema = (key: MyEnumType) => z.object({ [`${key}-action`]: z.string(), // 自动拼接出和外层键对应的action键 rest: z.record(z.unknown()).optional() // 处理你提到的...rest部分,可换成具体类型 }); // 遍历枚举的所有选项,构建最终的API响应Schema const apiResponseSchema = z.object( Object.fromEntries( MyEnum.options.map(key => [key, createInnerSchema(key)]) ) ).strict(); // 加上.strict()可以禁止API返回枚举外的多余键,按需选择 // 测试下解析效果 const testData = { "title": { "title-action": "some title content", rest: { extra: "title info" } }, "body": { "body-action": "some body content" } }; const parsedResult = apiResponseSchema.parse(testData); console.log(parsedResult.title["title-action"]); // 输出 "some title content"
方法二:宽松匹配的Record方式(适合快速开发)
如果你对键的严格性要求不高,只是需要确保外层键是枚举值,内部结构相对统一,也可以用z.record快速实现:
// 定义通用的内部对象Schema const innerSchema = z.object({ // 注意:这种方式没法让内部键和外层键动态关联,适合内部键不依赖外层的场景 action: z.string(), rest: z.record(z.unknown()).optional() }); // 直接用枚举作为键类型,内部用通用Schema const apiResponseSchema = z.record(MyEnum, innerSchema);
小提示
- 如果你的
...rest有固定的结构(比如有特定键和类型),直接把z.record(z.unknown())换成对应的z.object({ ... })就行。 - 方法一生成的是严格对象类型,TypeScript会自动提示外层只能用枚举内的键,内部对象的
{key}-action也会有精准提示,开发体验更好。
内容来源于stack exchange
相关产品推荐
相关产品推荐

