如何基于React Hook Form的useFormContext实现输入组件name类型安全
实现基于Form Schema的类型安全输入组件
核心思路
通过泛型将输入组件与表单Schema类型绑定,利用React Hook Form提供的FieldPath类型工具,限制name属性只能是Schema中的合法字段名,同时让register和errors自动适配Schema类型,实现全链路类型安全。
修改步骤与代码实现
1. 导入必要的类型工具
首先导入React Hook Form提供的类型工具,用于约束组件的泛型逻辑:
import { ExclamationCircleIcon } from "@heroicons/react/20/solid"; import React from "react"; import { useFormContext, FieldPath, UseFormReturn } from "react-hook-form";
2. 定义泛型Props与组件
将组件和Props改为泛型结构,绑定表单Schema类型,让name属性只能接收Schema内的合法字段:
// 泛型Props,T代表表单Schema的类型 interface InputProps<T extends object> { label: string; name: FieldPath<T>; // 仅允许T中的合法字段名 type?: string; placeholder?: string; } // 泛型组件,接收表单Schema类型T export function InputWithValidationError<T extends object>({ label, name, type = "text", placeholder, }: InputProps<T>) { // 为useFormContext指定类型,确保register和errors与Schema匹配 const { register, formState: { errors } } = useFormContext<UseFormReturn<T>>(); // errors自动适配Schema类型,无需手动类型断言 const error = errors[name]?.message; return ( <div> <label htmlFor={name}>{label}</label> <input id={name} type={type} placeholder={placeholder} {...register(name)} // 此时register仅接受T中的合法字段 /> {error && <p className="text-red-500 flex items-center gap-1"> <ExclamationCircleIcon className="w-4 h-4" /> {error} </p>} </div> ); }
3. 表单上下文的类型传递
在使用FormProvider时,传入带有明确Schema类型的useForm返回值,子组件会自动继承该类型:
import { useForm, FormProvider } from "react-hook-form"; // 定义表单Schema类型 type LoginFormSchema = { email: string; password: string; }; export default function LoginPage() { // 传入Schema类型初始化表单方法 const methods = useForm<LoginFormSchema>(); return ( <FormProvider {...methods}> <form onSubmit={methods.handleSubmit((data) => console.log(data))}> {/* TypeScript会自动提示"email"和"password" */} <InputWithValidationError label="Email" name="email" /> <InputWithValidationError label="Password" name="password" /> {/* ❌ 输入"username"会直接触发TypeScript错误 */} {/* <InputWithValidationError label="Username" name="username" /> */} <button type="submit">登录</button> </form> </FormProvider> ); }
关键说明
FieldPath<T>:React Hook Form提供的类型工具,提取T中所有合法的字段路径(支持嵌套字段,如user.email)- 泛型组件:通过泛型绑定表单Schema,让组件可以复用在不同Schema的表单场景中
- 类型化上下文:
useFormContext<UseFormReturn<T>>确保register和errors的类型与Schema完全匹配,避免冗余的类型断言
内容的提问来源于stack exchange,提问作者sansalgo
相关产品推荐
相关产品推荐

