react-hook-form与Zod类型推断错误问题排查与解决
Type 'string' is not assignable to type 'Date' 错误分析与修复
问题代码
const scheme = z.object({ date: z .string() .transform((value) => value) .pipe(z.coerce.date()), }) const useForm = <TFieldValues extends FieldValues>(options: { scheme: z.Schema<TFieldValues> }) => { const { scheme } = options return useRHForm<TFieldValues>({ resolver: zodResolver(scheme), }) } useForm({ scheme, // Type 'string' is not assignable to type 'Date'. })
调用useForm时出现类型错误:Type 'string' is not assignable to type 'Date'
错误原因
- 你的Zod schema里,
date字段通过.pipe(z.coerce.date())实现了输入是string、输出是Date的类型转换,但Zod的z.Schema<T>默认描述的是schema的输出类型(也就是转换后的Date类型)。 - 封装的
useRHForm(react-hook-form实例)中,TFieldValues对应的是表单的输入值类型(用户实际输入的string类型),两者类型不匹配,触发TypeScript报错。 - 当前
useForm的泛型参数直接把TFieldValues绑定到了schema的输出类型,没有区分输入和输出的类型差异,这是问题核心。
修复方案
修改useForm的泛型定义,利用Zod内置的类型提取工具,区分schema的输入和输出类型,让表单输入类型和schema的输入类型对齐:
import { z } from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; import { FieldValues, useForm as useRHForm } from "react-hook-form"; const scheme = z.object({ date: z .string() .transform((value) => value) .pipe(z.coerce.date()), }); // 提取Zod schema的输入类型 type SchemaInput<T extends z.Schema> = z.inferInput<T>; const useForm = <TSchema extends z.Schema>(options: { scheme: TSchema }) => { const { scheme } = options; // 让useRHForm的泛型使用schema的输入类型 return useRHForm<SchemaInput<TSchema>>({ resolver: zodResolver(scheme), }); }; // 调用不再报错 useForm({ scheme, });
如果业务场景需要表单字段值直接使用转换后的Date类型,可以在useRHForm中配置defaultValues并设置合适的校验模式确保类型完全对齐,但更推荐上面的方案——因为表单初始输入通常为string类型。
内容的提问来源于stack exchange,提问作者Pavel Perevezencev
相关产品推荐
相关产品推荐

