泛型validate函数将Zod Schema带默认值属性转为可选问题求助
原因分析
问题出在你的泛型辅助函数没有正确推导Zod schema包含默认值后的输出类型:
- 直接调用
schema.parse()时,Zod会自动将带default()的属性标记为必填——因为解析过程中会自动注入默认值,最终返回的结果一定包含该属性。 - 但你的辅助函数可能错误地基于schema的输入类型(即允许缺失该属性的类型)推导返回值,或者泛型约束没有正确关联Zod的完整输出类型,导致IntelliSense误判该属性为可选。
举个典型的错误示例:
// 错误的辅助函数定义 async function oldValidate<T>(schema: z.ZodSchema<T>, formData: FormData): Promise<T> { const rawData = Object.fromEntries(formData); return schema.parse(rawData); } // 调用时TS会推断T为 { email: string; sendActivationEmail?: boolean } // 导致IntelliSense认为sendActivationEmail是可选的 const result = await oldValidate(createUserSchema, new FormData());
这里的T被推导为schema的输入类型(允许sendActivationEmail缺失),但实际schema.parse()会补上默认值,返回的是必填该属性的输出类型。
解决办法
修改辅助函数的泛型定义,让返回类型直接绑定Zod schema的输出类型,而不是依赖手动指定的泛型参数:
方案1:基于Schema泛型推导输出类型
import { z, ZodSchema } from 'zod'; async function validate<Schema extends ZodSchema>( schema: Schema, formData: FormData ): Promise<z.infer<Schema>> { // 将FormData转为普通对象 const rawData = Object.fromEntries(formData); // 交给Zod处理解析和默认值注入 return schema.parse(rawData); }
方案2:使用safeParse的类型推导(如果需要错误处理)
async function validate<Schema extends ZodSchema>( schema: Schema, formData: FormData ): Promise<z.infer<Schema>> { const rawData = Object.fromEntries(formData); const parseResult = schema.safeParse(rawData); if (!parseResult.success) { throw new Error(parseResult.error.issues.map(i => i.message).join(', ')); } // parseResult.data的类型自动为schema的输出类型,带必填的默认值属性 return parseResult.data; }
效果验证
调用修改后的函数时,IntelliSense会正确识别带默认值的属性为必填:
const createUserSchema = z.object({ email: z.string().email(), sendActivationEmail: z.boolean().default(true) }); const result = await validate(createUserSchema, new FormData()); // result.sendActivationEmail 类型为 boolean(必填),而非 boolean | undefined
内容的提问来源于stack exchange,提问作者Joe Shiels
相关产品推荐
相关产品推荐

