如何无需重新声明即可解析Zod Schema的输出?
如何基于带transform的Zod Schema获取其输出结构的可解析Schema?
问题描述
我定义了如下带transform的Zod Schema:
export const Schema = z .object({ cover_image_path: z.string().nullish(), }) .transform((prev) => ({ coverImagePath: prev.cover_image_path, }));
可以用Schema.parse(input)解析原始输入,但我想直接基于转换后的输出结构做校验,不想额外声明重复的Schema:
// 不想额外写这个重复的Schema export const Schema = z .object({ coverImagePath: z.string().nullish(), });
尝试用Schema._output.parse(...)时发现_output只是TypeScript类型,不是运行时Schema实例,没法调用parse方法,该怎么解决?
解决方案
方案1:拆分定义,复用输出Schema
最稳妥的方式是先单独定义输出结构的Schema,再基于它构建输入Schema,避免重复代码:
import { z } from "zod"; // 定义输出结构的Schema,后续可直接用于校验转换后的数据 const OutputSchema = z.object({ coverImagePath: z.string().nullish(), }); // 基于输出结构反向定义输入Schema并添加转换逻辑 const InputSchema = z .object({ cover_image_path: z.string().nullish(), }) .transform((prev) => ({ coverImagePath: prev.cover_image_path, }));
使用时:
- 用
InputSchema.parse(rawInput)处理原始输入并完成转换 - 用
OutputSchema.parse(transformedData)校验转换后的结果
方案2:从输出类型自动生成运行时Schema
如果不想手动维护两个Schema,可以利用Zod的类型推导,从输入Schema的输出类型反向生成运行时Schema:
import { z } from "zod"; const InputSchema = z .object({ cover_image_path: z.string().nullish(), }) .transform((prev) => ({ coverImagePath: prev.cover_image_path, })); // 从输入Schema的输出类型生成对应的运行时Schema const OutputSchema = z.object(z.infer<typeof InputSchema> as any);
这种方式适合结构简单的场景,复杂嵌套结构可能需要手动调整类型断言。
方案3:扩展Zod实例(适合频繁使用的场景)
如果项目中经常需要从带transform的Schema获取输出Schema,可以给Zod扩展一个自定义方法:
import { z } from "zod"; // 扩展Zod的类型声明 declare module "zod" { interface ZodType<any, any, any> { getOutputSchema(): ZodType; } } // 实现扩展方法 z.ZodType.prototype.getOutputSchema = function() { return z.object(z.infer<typeof this> as any); }; // 使用示例 const InputSchema = z .object({ cover_image_path: z.string().nullish(), }) .transform((prev) => ({ coverImagePath: prev.cover_image_path, })); // 获取输出Schema并校验 const OutputSchema = InputSchema.getOutputSchema(); OutputSchema.parse(InputSchema.parse(rawInput));
内容的提问来源于stack exchange,提问作者Coding Edgar
相关产品推荐
相关产品推荐

