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

如何为React TypeScript表单组件的Props添加第二个接口

如何将HTML表单原生属性类型集成到自定义React Hook Form组件的Props中

原始代码

import { ReactNode, DetailedHTMLProps, FormHTMLAttributes } from "react";
import {
  FieldValues,
  SubmitHandler,
  useForm,
  UseFormReturn,
} from "react-hook-form";

// I want to add this type to the FormProps interface
// DetailedHTMLProps<FormHTMLAttributes<HTMLFormElement>, HTMLFormElement>

interface FormProps<TFormValues extends FieldValues> {
  onSubmit: SubmitHandler<TFormValues>;
  children: (methods: UseFormReturn<TFormValues>) => ReactNode;
}

export const Form = <TFormValues extends Record<string, any>>({
  onSubmit,
  children,
}: FormProps<TFormValues>) => {
  const methods = useForm<TFormValues>();

  return (
    <form onSubmit={methods.handleSubmit(onSubmit)}>{children(methods)}</form>
  );
};

问题需求

希望让自定义Form组件支持所有原生HTML表单的属性,需要将DetailedHTMLProps<FormHTMLAttributes<HTMLFormElement>, HTMLFormElement>类型集成到FormProps接口中。

解决方案

通过接口扩展+类型排除实现,既保留原生表单属性的类型支持,又避免与组件自定义的onSubmit属性冲突:

  1. 让FormProps扩展原生表单属性类型,但用Omit排除原生的onSubmit(因为组件需要的是react-hook-form的SubmitHandler类型,而非原生表单的提交事件类型)
  2. 将剩余的原生属性解构后传递给底层的<form>元素

修改后的完整代码:

import { ReactNode, DetailedHTMLProps, FormHTMLAttributes } from "react";
import {
  FieldValues,
  SubmitHandler,
  useForm,
  UseFormReturn,
} from "react-hook-form";

interface FormProps<TFormValues extends FieldValues> 
  extends Omit<DetailedHTMLProps<FormHTMLAttributes<HTMLFormElement>, HTMLFormElement>, 'onSubmit'> {
  onSubmit: SubmitHandler<TFormValues>;
  children: (methods: UseFormReturn<TFormValues>) => ReactNode;
}

export const Form = <TFormValues extends FieldValues>({
  onSubmit,
  children,
  ...rest // 解构所有原生表单属性
}: FormProps<TFormValues>) => {
  const methods = useForm<TFormValues>();

  return (
    // 将原生属性传递给底层form标签
    <form {...rest} onSubmit={methods.handleSubmit(onSubmit)}>
      {children(methods)}
    </form>
  );
};

说明

  • 使用Omit排除原生onSubmit:原生表单的onSubmit类型是(e: FormEvent<HTMLFormElement>) => void,与组件需要的SubmitHandler<TFormValues>类型不兼容,因此必须排除后重新定义
  • 通过...rest接收并传递原生属性:这样你的自定义Form组件就可以像原生<form>标签一样使用所有属性,比如className、style、id、enctype、autocomplete等
  • 统一泛型约束:将组件的泛型约束从Record<string, any>改为FieldValues,与接口的约束保持一致,更符合react-hook-form的类型规范

内容的提问来源于stack exchange,提问作者Millenial2020

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 12:10:37