You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 06:30:53