为自定义React Hook Form组件的验证规则推断字段类型
如何让自定义表单组件根据name自动推断验证函数的value类型?
我基于react-hook-form开发了一个接收UseControllerProps的自定义组件,定义如下:
type CustomComponentProps<T extends FieldValues> = UseControllerProps<T>;
组件实现:
function CustomComponent<T extends FieldValues>({ control, name, rules, ...props }: CustomComponentProps<T>) { const { field } = useController<T>({ control, name, rules, }); // 组件实现逻辑 }
表单值类型定义:
type FormValue = { input1: string; input2: number; input3: boolean; };
使用组件时,指定name="input2"能正常运行,但添加验证规则时,验证函数的value类型被推断为string | number | boolean,而非预期的number:
const { control } = useForm<FormValue>(); <CustomComponent control={control} name="input2" rules={{ validate: { // value 类型为 'string' | 'number' | 'boolean',不符合预期 someValidation: (value) => value || 'error', }, }} />
解决方案
需要给自定义组件新增一个泛型参数来约束字段路径,让TypeScript能根据name自动推断对应字段的类型:
- 修改组件Props类型,引入字段路径泛型
import { FieldValues, UseControllerProps, Path, PathValue } from 'react-hook-form'; // 拆分UseControllerProps,用泛型N约束name的路径 type CustomComponentProps<T extends FieldValues, N extends Path<T>> = Omit<UseControllerProps<T>, 'name'> & { name: N; };
- 更新组件定义,添加泛型参数N
function CustomComponent<T extends FieldValues, N extends Path<T>>({ control, name, rules, ...props }: CustomComponentProps<T, N>) { const { field } = useController<T>({ control, name, rules, }); // 组件实现逻辑 return <input {...field} {...props} />; // 示例渲染逻辑 }
- 使用组件时的效果
此时指定name="input2",验证函数的value会自动推断为number:
const { control } = useForm<FormValue>(); <CustomComponent control={control} name="input2" rules={{ validate: { someValidation: (value) => { // value 类型现在是number,符合预期 return value > 0 || '输入必须大于0'; }, }, }} />
原理说明
通过新增泛型N extends Path<T>来限定name的合法路径,再借助react-hook-form内置的PathValue<T, N>工具类型,从表单值类型T中提取对应路径N的字段类型,最终让TypeScript自动推导验证函数中value的具体类型。
内容的提问来源于stack exchange,提问作者Henny Lee
相关产品推荐
相关产品推荐

