如何在Zod中遍历属性并获取其类型与配置信息?
Zod Schema 属性遍历与配置项检查方案
问题描述
给定以下Zod基础代码:
import { z } from 'zod' const Post = z.object({ title: z.string(), }) const User = z.object({ name: z.string(), email: z.string().optional(), posts: z.array(Post), loginCount: z.number().min(1) })
需要遍历Schema的属性并检查属性配置项,实现类似如下逻辑:
for (const name in shape) { const prop = shape[name] if (prop.min != null) { console.log(`Has min ${prop.min}`) } if (prop.max != null) { console.log(`Has max ${prop.max}`); } if (prop.optional === true) { console.log(`Is optional`); } if (prop.type) { if (prop.type is array) { prop.type.forEach(item => { console.log(`Has array item type ${item.name}`) }) } else if (prop.type is union) { // ... show union type names } else { // show basic type name } } }
核心需求包括:
- 获取每个Schema的键名
- 获取属性允许的类型(用于数据库表结构生成等场景)
- 自动生成文档
- 其他元数据提取类需求
解决方案
Zod提供shape属性访问对象Schema的属性,但要获取类型约束、可选性等配置,需结合Zod内部的_def属性实现,以下是具体代码和说明:
1. 递归遍历与配置项检查实现
import { z, ZodType, ZodObject, ZodString, ZodNumber, ZodArray, ZodOptional, ZodUnion } from 'zod'; // 递归分析Schema的函数 function analyzeSchema(schema: ZodType, parentKey = '') { // 处理可选类型:先提取内部真实Schema if (schema instanceof ZodOptional) { console.log(`${parentKey}: 是可选属性`); analyzeSchema(schema.unwrap(), parentKey); return; } // 处理数组类型 if (schema instanceof ZodArray) { console.log(`${parentKey}: 类型为数组`); analyzeSchema(schema.element, `${parentKey}[元素]`); return; } // 处理联合类型 if (schema instanceof ZodUnion) { console.log(`${parentKey}: 类型为联合类型,包含以下子类型:`); schema.options.forEach((subSchema, index) => { analyzeSchema(subSchema, `${parentKey}[${index}]`); }); return; } // 处理对象类型:递归遍历所有属性 if (schema instanceof ZodObject) { Object.entries(schema.shape).forEach(([key, propSchema]) => { const currentKey = parentKey ? `${parentKey}.${key}` : key; analyzeSchema(propSchema, currentKey); }); return; } // 处理基础类型(字符串、数字) if (schema instanceof ZodString) { console.log(`${parentKey}: 类型为字符串`); // 提取字符串约束(最小长度、最大长度等) schema._def.checks.forEach(check => { if (check.kind === 'min') console.log(`${parentKey}: 最小长度 ${check.value}`); if (check.kind === 'max') console.log(`${parentKey}: 最大长度 ${check.value}`); }); } else if (schema instanceof ZodNumber) { console.log(`${parentKey}: 类型为数字`); // 提取数字约束(最小值、最大值等) schema._def.checks.forEach(check => { if (check.kind === 'min') console.log(`${parentKey}: 最小值 ${check.value}`); if (check.kind === 'max') console.log(`${parentKey}: 最大值 ${check.value}`); }); } } // 调用函数分析User Schema analyzeSchema(User);
2. 运行输出示例
执行上述代码后,控制台会输出:
name: 类型为字符串 email: 是可选属性 email: 类型为字符串 posts: 类型为数组 posts[元素].title: 类型为字符串 loginCount: 类型为数字 loginCount: 最小值 1
3. 扩展应用场景
- 数据库表结构生成:在分析过程中,将Zod类型映射为数据库字段类型(如
z.string()对应VARCHAR,z.number()对应INT),同时记录可选性、约束条件,自动生成建表SQL语句。 - 文档生成:把分析结果整理成Markdown/HTML格式,包含字段名、类型、约束、可选性等信息,快速生成API或数据结构文档。
注意事项
_def是Zod的内部属性,虽目前稳定,但官方未承诺永久兼容。若需长期维护,建议通过Zod的refine方法或自定义类型扩展来封装元数据,避免直接依赖内部属性。- 对于枚举、日期、自定义校验类型等复杂场景,可在
analyzeSchema函数中添加对应的instanceof判断分支,扩展处理逻辑。
内容的提问来源于stack exchange,提问作者Lance Pollard
相关产品推荐
相关产品推荐

