如何为Zod编写封装object与default方法的类型化辅助函数
Zod 类型安全辅助函数:返回带默认空对象的对象 Schema
问题分析
你需要创建一个辅助函数,接收 Zod object 方法的参数,返回已应用 .default({}) 的 Zod 对象,同时替换掉 any 类型,用泛型实现正确的类型约束。
解决方案
利用 Zod 内置的类型(ZodRawShape、ObjectParams、ZodObject)来约束泛型,实现类型安全的函数:
基础实现(保留原字段必填性)
这个版本严格保留你传入的字段约束,仅添加空对象默认值(注意:如果有必填字段,直接 parse 空对象会触发校验错误):
import { z, ZodRawShape, ZodObject, ObjectParams } from "zod"; function objectWithDefault<Shape extends ZodRawShape>( shape: Shape, params?: ObjectParams ): ZodObject<Shape> { // 用 as 断言是安全的,因为 .default() 不会改变 Schema 的结构类型 return z.object(shape, params).default({}) as ZodObject<Shape>; }
增强实现(自动转为可选字段)
如果需要默认空对象能通过校验,可以自动将所有字段转为可选类型:
import { z, ZodRawShape, ZodObject, ObjectParams, ZodTypeAny } from "zod"; // 定义将 Shape 中所有字段转为可选的类型 type OptionalShape<Shape extends ZodRawShape> = { [K in keyof Shape]: Shape[K] extends ZodTypeAny ? Shape[K].optional() : never; }; function objectWithDefault<Shape extends ZodRawShape>( shape: Shape, params?: ObjectParams ): ZodObject<OptionalShape<Shape>> { // 将传入的每个 schema 转为可选 const optionalShape = Object.fromEntries( Object.entries(shape).map(([key, schema]) => [key, schema.optional()]) ) as OptionalShape<Shape>; return z.object(optionalShape, params).default({}); }
使用示例
// 基础实现的使用 const BaseUserSchema = objectWithDefault({ name: z.string(), // 必填字段 age: z.number().optional() }); // 类型推断:z.infer<typeof BaseUserSchema> = { name: string; age?: number } // BaseUserSchema.parse({}) // 会报错,因为 name 是必填项 // 增强实现的使用 const OptionalUserSchema = objectWithDefault({ name: z.string(), age: z.number() }); // 类型推断:z.infer<typeof OptionalUserSchema> = { name?: string; age?: number } const user = OptionalUserSchema.parse({}); // 成功,user = {}
内容的提问来源于stack exchange,提问作者cubabit
相关产品推荐
相关产品推荐

