如何使用Zod为现有formSchema动态添加属性?
用Zod动态生成包含props字段的FormSchema
核心思路
Zod提供了.merge()方法,可以将两个Object类型的Schema合并。我们只需要把optionProps里的字段转换成对应的Zod规则,再和已有的基础Schema合并即可。
具体实现步骤
- 定义基础Schema
先把固定字段抽出来作为基础Schema:
import { z } from "zod"; const baseFormSchema = z.object({ quantity: z.number() .positive() .min(1) .max(20), price: z.number() .positive() });
- 从optionProps生成动态字段Schema
遍历optionProps,用reduce把每个项转换成Zod字段规则,键为optionFor的值,根据required设置必填/可选:
const optionProps = [ { "name": "select one", "options": [{"name": "lettus"}, {"name": "cucumber"}], "optionFor": "salad", "required": true }, { "name": "select one", "options": [{"name": "can of coke"}, {"name": "pepsi"}], "optionFor": "extra", "required": true } ]; const dynamicFieldsSchema = z.object( optionProps.reduce((acc, item) => { acc[item.optionFor] = item.required ? z.string().required(`${item.optionFor}不能为空`) : z.string().optional(); return acc; }, {}) );
- 合并两个Schema
用.merge()方法合并基础Schema和动态字段Schema,得到最终的FormSchema:
const finalFormSchema = baseFormSchema.merge(dynamicFieldsSchema);
进阶优化:限制可选值
如果要确保字段值只能是options里的name,可以把z.string()换成z.enum(),直接限定可选范围:
const dynamicFieldsSchema = z.object( optionProps.reduce((acc, item) => { const optionNames = item.options.map(opt => opt.name); acc[item.optionFor] = item.required ? z.enum(optionNames).required(`${item.optionFor}必须选择指定选项`) : z.enum(optionNames).optional(); return acc; }, {}) );
验证测试
用parse方法测试是否符合预期:
// 合法数据 const validData = { quantity: 3, price: 15.5, salad: "cucumber", extra: "can of coke" }; console.log(finalFormSchema.parse(validData)); // 正常返回数据 // 非法数据(salad选了不在选项里的值) const invalidData = { quantity: 3, price: 15.5, salad: "tomato", extra: "can of coke" }; try { finalFormSchema.parse(invalidData); } catch (err) { console.error(err.errors); // 输出错误提示 }
内容的提问来源于stack exchange,提问作者jahid
相关产品推荐
相关产品推荐

