You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 16:10:25