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

Zod结合react-hook-form使用时,.default(false)被解析为boolean | undefined导致类型不匹配问题

Zod结合react-hook-form使用时,.default(false)被解析为boolean | undefined导致类型不匹配问题

这个问题我之前也碰到过,其实是Zod和react-hook-form的类型系统设计差异导致的,不是bug,咱们一步步拆解:

问题根源

当你在Zod Schema里用.default(false)时,Zod的逻辑是:输入可以缺失这个字段,解析时会自动用默认值补全,所以Zod内部会把这个字段的输入类型标记为可选(boolean | undefined);但z.infer<typeof TestSchema>得到的是解析后的输出类型——因为默认值会补全,所以输出里这个字段是必填的boolean。

而react-hook-form的zodResolver需要同时匹配「用户输入的类型」和「解析后的输出类型」,当你手动给useForm指定TestType(输出类型)时,resolver期望的输入类型(允许缺失)和你指定的表单类型(必填)就产生了冲突,于是出现了那个类型不兼容的报错。

解决方案

有两种简单的解决方式,根据你的需求选就行:

方案1:让useForm自动推导类型(推荐)

不用手动给useForm指定泛型,让zodResolver自动帮你推导正确的表单类型——这样react-hook-form会自动对齐Zod的输入输出类型,不会有冲突:

const TestSchema = z.object({
  isFeatured: z.boolean().default(false),
});

// 去掉<TestType>泛型,让resolver自动推导
const form = useForm({
  resolver: zodResolver(TestSchema),
  mode: 'onChange',
  defaultValues: {
    isFeatured: false,
  },
});

// 此时form的values类型会被正确推断为{ isFeatured: boolean }

方案2:把默认值移到react-hook-form的defaultValues里

如果你一定要手动指定泛型,可以去掉Zod的.default(),把默认值放在react-hook-form的defaultValues中,这样Zod的Schema会要求输入必须包含该字段,和你手动指定的TestType完全对齐:

const TestSchema = z.object({
  isFeatured: z.boolean(), // 移除Zod的default设置
});

type TestType = z.infer<typeof TestSchema>;

const form = useForm<TestType>({
  resolver: zodResolver(TestSchema),
  mode: 'onChange',
  defaultValues: {
    isFeatured: false, // 用react-hook-form的defaultValues设置默认值
  },
});

补充验证

你之前测试const myVar:TestType = {}报错是对的,因为TestType是Zod解析后的输出类型,确实要求isFeatured必填;而resolver报错里的{ isFeatured?: boolean | undefined }是Zod允许的输入类型(因为默认值会补全),这两个类型本来就不一样——所以手动指定泛型才会冲突,让自动推导或者调整默认值的位置就能解决问题。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 10:54:29