使用Zod Schema实现工厂模式时遇到类型推断问题
解决Zod工厂模式中的类型推断问题
问题出在你当前的泛型定义上:你只约束了schemas的键名类型T,但把schemas的值宽泛地定义为z.ZodSchema,这会让TypeScript丢失每个具体Schema的类型细节,导致filter无法被正确推断。
修改方案是让泛型直接约束整个schemas对象的类型,保留每个Schema的具体结构:
import { z } from 'zod'; export const makeClient = <S extends Record<string, z.ZodSchema>>({ schemas, }: { schemas: S; }) => { return { async findOne<K extends keyof S>({ name, filter, }: { name: K; filter: z.infer<S[K]>; }) { return { name, filter }; }, }; }; // 使用示例 const client = makeClient({ schemas: { test: z.object({ value: z.number(), }), user: z.object({ id: z.string(), email: z.string().email(), }), }, }); // 现在filter会自动推断对应Schema的类型 client.findOne({ name: "test", filter: { value: 123, // 类型推断为number,错误类型会触发TS报错 } }); client.findOne({ name: "user", filter: { id: "u_123", email: "user@example.com" } });
为什么这样改能生效?
- 泛型
S会完整保留传入的schemas对象的结构,包括每个键对应的具体Zod Schema类型,而不是把所有值都统一为宽泛的z.ZodSchema。 - 调用
findOne时,指定name为某个键K后,z.infer<S[K]>可以准确提取该Schema对应的TS类型,TypeScript就能自动提示filter的结构并做类型校验。
内容的提问来源于stack exchange,提问作者Kartal
相关产品推荐
相关产品推荐

