如何在React Hook Form的TypeScript泛型组件中约束字段值类型?
给React Hook Form可复用控件添加类型约束,强制字段类型为PropertyDTO
要强制TFieldValues[TName]必须是PropertyDTO类型,你可以通过泛型约束或条件类型校验实现,以下是两种实用方案:
方案一:通过条件类型校验props合法性
直接在组件的props类型中添加判断,只有当目标字段类型匹配PropertyDTO时,组件才能正常使用:
import { FieldValues, FieldPath, useController } from "react-hook-form"; // 假设已定义目标类型 type PropertyDTO = { id: string; name: string; }; function PropertyDropdownControlled< TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues> >(props: { name: TName } & (TFieldValues[TName] extends PropertyDTO ? {} : never)) { const { field } = useController({ name, control: props.control }); // 组件渲染逻辑(示例) return ( <select {...field}> {/* 渲染PropertyDTO选项 */} </select> ); }
方案二:约束TName只能是符合类型要求的字段名
这种方式会让TypeScript自动提示合法的字段名,开发体验更友好:
import { FieldValues, FieldPath, useController } from "react-hook-form"; type PropertyDTO = { id: string; name: string; }; function PropertyDropdownControlled< TFieldValues extends FieldValues, // 仅允许TName是TFieldValues中类型为PropertyDTO的字段路径 TName extends { [K in FieldPath<TFieldValues>]: TFieldValues[K] extends PropertyDTO ? K : never }[FieldPath<TFieldValues>] >(props: { name: TName; control: Control<TFieldValues> }) { const { field } = useController({ name, control: props.control }); return ( <select {...field}> {/* 渲染选项 */} </select> ); }
使用示例
定义表单值类型:
type CurrentFormValues = { Property: PropertyDTO; // 符合约束,可正常使用 OtherField: string; // 不符合约束,会触发类型错误 };
合法使用(无类型错误):
<PropertyDropdownControlled<CurrentFormValues> name="Property" control={control} />
非法使用(TypeScript会报错):
// 错误:'OtherField'的类型是string,不匹配PropertyDTO <PropertyDropdownControlled<CurrentFormValues> name="OtherField" control={control} />
内容的提问来源于stack exchange,提问作者EtienneT
相关产品推荐
相关产品推荐

