如何从Zod泛型函数生成的Schema中推导类型?
问题描述
我编写了一个用于生成简单Schema的泛型函数LeafSchema:
const LeafSchema = <T extends z.ZodTypeAny>(valueSchema: T) => { return z.object({ value: valueSchema }) }
我希望通过ReturnType和z.infer推导该生成Schema的类型,为此定义了泛型类型Leaf:
type Leaf<T extends z.ZodTypeAny> = z.infer<ReturnType<typeof LeafSchema<T>>> const getLeafValue = <T extends z.ZodTypeAny>(leaf: Leaf<T>) => leaf.value
但调用getLeafValue并传入{ 'value': 123 }时,返回值类型仍为any,需要修复这个泛型写法的问题。
问题根源
getLeafValue的泛型参数T被约束为z.ZodTypeAny,但调用时传入的是普通对象{value:123}——TypeScript无法从这个原始值反向推导出对应的Zod Schema类型T,因此T会默认推断为z.ZodTypeAny,最终z.infer<...>的结果就是any。
修复方案
方案1:直接基于值类型定义泛型(最简洁)
绕过Zod Schema的泛型约束,直接针对Leaf结构的值类型推导:
type Leaf<V> = { value: V } const getLeafValue = <V>(leaf: Leaf<V>) => leaf.value // 调用时返回值类型自动推断为number const val = getLeafValue({ value: 123 })
方案2:保留与Zod的关联
如果需要维持Leaf类型和Zod Schema的绑定,有两种实现方式:
方式A:通过预定义的Schema实例推导类型
先创建具体的Leaf Schema,再用它约束输入:
// 定义具体的数字类型Leaf Schema const NumberLeafSchema = LeafSchema(z.number()) type NumberLeaf = z.infer<typeof NumberLeafSchema> const getLeafValue = <T extends z.ZodTypeAny>(leaf: z.infer<ReturnType<typeof LeafSchema<T>>>) => leaf.value // 先通过Schema校验得到类型安全的对象,再传入函数 const validLeaf = NumberLeafSchema.parse({ value: 123 }) const val = getLeafValue(validLeaf) // 返回值类型为number
方式B:让Leaf类型基于值类型关联Zod Schema
调整Leaf的泛型定义,让值类型作为入口:
type Leaf<V> = z.infer<ReturnType<typeof LeafSchema<z.ZodType<V>>>> const getLeafValue = <V>(leaf: Leaf<V>) => leaf.value // 调用时自动推断返回值为number const val = getLeafValue({ value: 123 })
内容的提问来源于stack exchange,提问作者Azael
相关产品推荐
相关产品推荐

