Zod createQuerySchema类型推断异常:缺失条件键与枚举值
解决Zod动态创建QuerySchema时类型推断不准确的问题
问题分析
你编写的createQuerySchema函数期望根据传入的config对象动态生成Zod schema,且通过z.infer得到的类型仅包含实际传入的键,每个键的类型是对应数组值的枚举联合类型。但当前实现中,z.infer得到的类型包含了所有可选键(include和fields)且类型为unknown,这是因为泛型定义没有正确关联返回的Zod对象类型,TS无法准确推断出动态构建的schema结构。
解决方案
通过调整泛型定义,让函数捕获传入config的具体类型,并基于该类型显式指定返回的Zod对象类型,从而让TS能正确推导z.infer的结果。
修改后的完整代码
import { z, ZodObject, ZodRawShape } from "zod"; const createEnumSchema = <const T extends readonly [string, ...string[]]>(values: T) => z.enum(values).optional(); type QueryConfig = Partial<{ fields: readonly [string, ...string[]]; include: readonly [string, ...string[]]; }>; const createQuerySchema = <const C extends QueryConfig>(config: C) => { const shape: ZodRawShape = {}; if (config.fields) { shape.fields = createEnumSchema(config.fields); } if (config.include) { shape.include = createEnumSchema(config.include); } return z.object(shape) as ZodObject<{ [K in keyof C]: C[K] extends readonly [string, ...string[]] ? z.ZodOptional<z.ZodEnum<C[K]>> : never; }>; }; // 测试用例1:仅传入fields const querySchema = createQuerySchema({ fields: ["id", "status", "title"], }); type QueryType = z.infer<typeof querySchema>; // 类型结果:{ fields?: "id" | "status" | "title" | undefined } // 测试用例2:仅传入include const querySchema2 = createQuerySchema({ include: ["user", "comments"], }); type QueryType2 = z.infer<typeof querySchema2>; // 类型结果:{ include?: "user" | "comments" | undefined } // 测试用例3:同时传入fields和include const querySchema3 = createQuerySchema({ fields: ["id", "title"], include: ["user"], }); type QueryType3 = z.infer<typeof querySchema3>; // 类型结果:{ fields?: "id" | "title" | undefined; include?: "user" | undefined }
关键改动说明
- 调整
createEnumSchema:添加.optional(),让生成的枚举schema对应可选字段,与config中的可选键匹配。 - 单一泛型捕获config类型:用泛型
C捕获传入config的具体结构,替代原来分开的F和I,确保能准确获取实际传入的键。 - 显式指定返回类型:通过类型断言将
z.object(shape)的类型指定为ZodObject,其中每个键对应C中的键,值为对应的可选枚举类型,让TS能正确推导z.infer的结果。
内容的提问来源于stack exchange,提问作者Zorp
相关产品推荐
相关产品推荐

