如何正确设置react-hook-form中setValue的TypeScript类型并传参给子组件
react-hook-form 传递
setValue 到子组件的类型不匹配解决方案 报错原因
当父组件通过 useForm<Inputs> 显式指定表单的字段泛型为具体结构 Inputs 时,返回的 setValue 类型会被绑定为 UseFormSetValue<Inputs>。如果子组件在定义Props时,给 setValue、register 预留的类型是适配通用结构的 UseFormSetValue<Record<string, any>>,就会因为泛型结构不匹配触发TS类型校验报错:
Type 'UseFormSetValue<Inputs>' is not assignable to type 'UseFormSetValue<Record<string, any>>'
本质是TS的泛型匹配规则决定了:绑定了精确字段结构的函数类型,无法直接赋值给适配更宽松通用结构的同泛型类型,因为两者的参数约束范围不匹配。
正确修复方式
- 第一步:抽取统一的表单字段类型,作为父子组件共享的类型基准
不要在父子组件各自定义重复的表单字段类型,也不要在子组件Props里硬写Record<string, any>作为类型占位,统一抽离可复用的类型定义:// 公共表单字段类型,父子组件复用同一引用 type Inputs = { field1: string field2: number } - 第二步:子组件Props与父组件传入的类型对齐
从react-hook-form中导入对应的工具类型,和父组件使用的Inputs泛型保持一致,不要使用通用的Record<string, any>占位:
父组件传值时不需要额外处理,直接将解构出的import type { UseFormSetValue, UseFormRegister } from 'react-hook-form' // 定义子组件Props类型 type Field2Props = { setValue: UseFormSetValue<Inputs> register: UseFormRegister<Inputs> } const Field2 = ({ setValue, register }: Field2Props) => { // 子组件内部可正常调用setValue、register,且保留完整的TS类型提示 return ( <div> <input {...register('field1')} /> <button onClick={() => setValue('field2', 100)}> 触发字段值更新 </button> </div> ) }setValue、register传入子组件即可,类型校验会自动通过。 - 第三步:如果子组件需要跨不同表单结构复用,可定义为泛型组件
如果子组件不希望绑定固定的Inputs类型,可以将组件本身改为泛型结构,把表单类型从父组件透传下来,保留类型安全的同时提升复用性:import type { UseFormSetValue, UseFormRegister, FieldValues } from 'react-hook-form' // 泛型Props定义,约束表单字段结构继承react-hook-form的基础类型 type GenericFieldProps<T extends FieldValues> = { setValue: UseFormSetValue<T> register: UseFormRegister<T> } // 定义为泛型组件 const GenericField = <T extends FieldValues>({ setValue, register }: GenericFieldProps<T>) => { return ( <div> <button onClick={() => setValue('commonField' as keyof T, '统一值')}> 公共操作 </button> </div> ) }
注意:不要为了快速消除报错给传入的
setValue添加as any的类型断言,这种写法会完全绕过TS的类型检查,后续出现字段名写错、值类型不匹配的问题时不会触发编译提示,容易引入线上隐患。
内容的提问来源于stack exchange,提问作者vuvu
相关产品推荐
相关产品推荐

