如何基于预定义Type类生成严格类型的Zod Schema对象?
问题:开启
strictNullChecks后Zod Schema与类类型匹配错误 场景与代码
现有如下类定义:
class MyModel { propA: string propB: number propC: boolean constructor() { this.propA = '' this.propB = 123 this.propC = true } }
希望基于该类创建Zod Schema,保证键与对应类型匹配,目标结构如下:
const mySchema = z.object<SOME_GENERIC_METHOD_HERE<MyModel>>({ propA: z.string(), propB: z.number(), propC: z .boolean() .optional() .transform((i) => i), })
最初实现了一个泛型类型,在关闭strictNullChecks时可正常工作:
type ZodSchemaKeysFrom1<E> = { [k in keyof E]: ZodType<E[k]> } const mySchema = z.object<ZodSchemaKeysFrom1<MyModel>>({ propA: z.string(), propB: z.number(), propC: z .boolean() .optional() .transform((i) => i), }) type MySchemaFields = z.infer<typeof mySchema>
此时MySchemaFields被推断为:
type MySchemaFields = { propA?: string; propB?: number; propC?: boolean; }
问题
开启strictNullChecks以保证代码严谨性后,propC出现类型错误:
Type 'ZodEffects<ZodOptional<ZodBoolean>, boolean | undefined, boolean | undefined>' is not assignable to type 'ZodType<boolean, ZodTypeDef, boolean>'. Types of property '_type' are incompatible. Type 'boolean | undefined' is not assignable to type 'boolean'. Type 'undefined' is not assignable to type 'boolean'.ts(2322)
解决方案
错误根源是原泛型要求每个键对应的Zod类型必须严格输出类属性的类型(如boolean),但z.boolean().optional().transform(...)的输出类型是boolean | undefined,与要求不符。
修改泛型类型,允许Zod类型输出为类属性类型或undefined,即可兼容可选字段的场景:
import { z, ZodType } from "zod"; class MyModel { propA: string propB: number propC: boolean constructor() { this.propA = '' this.propB = 123 this.propC = true } } // 修改后的泛型类型 type ZodSchemaKeysFrom<E> = { [k in keyof E]: ZodType<E[k] | undefined>; }; const mySchema = z.object<ZodSchemaKeysFrom<MyModel>>({ propA: z.string(), propB: z.number(), propC: z .boolean() .optional() .transform((i) => i), }); type MySchemaFields = z.infer<typeof mySchema>; // 此时 MySchemaFields 推断为: // { propA: string; propB: number; propC?: boolean; }
说明
- 修改后的泛型
ZodSchemaKeysFrom<E>允许每个键对应的Zod类型输出E[k] | undefined,完美匹配optional()修饰后的字段类型。 - 开启
strictNullChecks后,TypeScript会严格校验类型兼容性,此泛型既保证了Schema键与类属性的对应关系,又兼容了可选字段的场景。
内容的提问来源于stack exchange,提问作者Islam Y-
相关产品推荐
相关产品推荐

