如何基于嵌套数据集自动生成react-hook-form的useForm泛型类型?
解决React Hook Form中watch自动补全的类型推导问题
要让watch方法具备精确的自动补全,核心是让TypeScript保留表单字段的具体键名,而非推断为宽泛的string类型。以下是两种可行的解决方案:
方法一:使用as const断言 + 映射类型
通过as const强制TypeScript锁定对象的键名和值的字面量类型,再通过映射类型将值统一为string:
import { useForm } from 'react-hook-form'; // 定义初始表单结构,as const 让TS保留精确的键名 const initialFormFields = { myrandominpuitname1: '', myrandominpuitname2: '', myrandominpuitname3: '' } as const; // 生成表单类型,将每个字段值的类型转为string type MyInputs = { [Key in keyof typeof initialFormFields]: string; }; export default function MyForm() { const { register, watch } = useForm<MyInputs>({ defaultValues: initialFormFields as MyInputs // 类型断言匹配MyInputs的string类型 }); // watch现在会自动补全三个字段名 const username = watch('myrandominpuitname1'); return ( <form> <input {...register('myrandominpuitname1')} placeholder="输入1" /> <input {...register('myrandominpuitname2')} placeholder="输入2" /> <input {...register('myrandominpuitname3')} placeholder="输入3" /> </form> ); }
方法二:使用satisfies关键字(TypeScript 4.9+)
satisfies可以在不改变类型推断的前提下,验证对象符合指定类型,同时保留具体键名:
import { useForm } from 'react-hook-form'; // satisfies 检查对象符合Record<string, string>,但TS仍保留具体键名 const initialFormFields = { myrandominpuitname1: '', myrandominpuitname2: '', myrandominpuitname3: '' } satisfies Record<string, string>; // 直接通过typeof推导类型,无需额外转换 type MyInputs = typeof initialFormFields; export default function MyForm() { const { register, watch } = useForm<MyInputs>({ defaultValues: initialFormFields }); // 自动补全功能正常生效 const inputValue = watch('myrandominpuitname2'); return ( <form> <input {...register('myrandominpuitname1')} /> <input {...register('myrandominpuitname2')} /> <input {...register('myrandominpuitname3')} /> </form> ); }
为什么之前的尝试失败?
如果不使用as const或satisfies,TypeScript会将对象的键推断为宽泛的string类型,此时typeof initialFormFields得到的是{ [key: string]: string }——这种类型没有具体的键名,所以watch无法提供自动补全。
内容的提问来源于stack exchange,提问作者ii iml0sto1
相关产品推荐
相关产品推荐

