如何将Zod Schema指定属性设为可选以适配Upsert场景?
解决方案
方法1:直接指定单个属性为可选
如果不需要保留原有的严格校验schema(用于数据库返回结果),可以直接在定义时给id字段加上.optional():
const upsertSchema = z.object({ id: z.string().optional(), name: z.string(), });
这样既满足id可选的需求,又保证name字段必填。
方法2:基于原Schema扩展(推荐)
因为原schema要用于数据库返回结果(id为必填主键),推荐通过extend方法复用原schema,仅修改id的约束:
// 原数据库返回用的schema,保持不变 const dbReturnSchema = z.object({ id: z.string(), name: z.string(), }); // 创建Upsert专用schema,将id设为可选 const upsertSchema = dbReturnSchema.extend({ id: z.string().optional(), });
这种方式避免重复定义字段,同时保留原schema的完整性。
方法3:用omit/partial组合实现
也可以通过omit移除原schema的id,再合并一个可选的id字段:
const upsertSchema = dbReturnSchema.omit({ id: true }).merge(z.object({ id: z.string().optional() }));
或者使用partial仅将指定字段设为可选,再和原schema合并:
const upsertSchema = z.partial({ id: true }).merge(dbReturnSchema);
z.partial({ id: true })只会对id字段应用可选约束,其他字段保持原有的必填要求。
测试验证
使用新的upsertSchema处理Upsert逻辑:
// 插入操作正常通过解析 const insertData = upsertSchema.parse({ name: 'My Name' }); // 更新操作正常通过解析 const updateData = upsertSchema.parse({ id: '123', name: 'My Name' }); user.upsert({ ...insertData, id: insertData?.id || generateId() });
此时Zod不会再抛出id字段缺失的错误,同时确保name字段始终存在。
内容的提问来源于stack exchange,提问作者Bambang Adhitya Permana
相关产品推荐
相关产品推荐

