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

React+TypeScript+useForm:表单字段复用的类型匹配问题

解决React Hook Form中Field组件name参数类型匹配问题

你遇到的错误是因为register函数期望的参数是FormValues类型的具体键(即"name" | "details"),但你把Field组件的name参数定义成了宽泛的string,导致类型不匹配。要自动同步FormValues的字段,不用手动维护联合类型,直接用keyof操作符即可:

修改后的核心代码

import { useForm } from 'react-hook-form';

function MyForm () {
    const { handleSubmit, register } = useForm<FormValues>();

    const onSubmit = handleSubmit ((data: FormValues) => {
        console.log({data});
    });

    // 将name的类型改为keyof FormValues,自动关联FormValues的所有键
    function Field({name}: {name: keyof FormValues}) {
        console.log({name})
        return (
            <>
                <input {...register(name)} />
            </>
        );
    }
    
    return (
        <form onSubmit={onSubmit}>
            <Field name="name" />
            <input {...register("name")} placeholder="name" />
            <input {...register("details")} placeholder="details" />
            <input type="submit" />
        </form>
    );
}

type FormValues = {
    name: string;
    details: string;
}

export default MyForm;

原理说明

  • keyof FormValues会自动推导为FormValues类型的所有键名组成的联合类型(这里就是"name" | "details"),后续只要修改FormValues的字段,Field组件的name参数类型会自动同步,完全不用手动维护联合类型。
  • 这样name参数的类型就和register函数要求的参数类型完全匹配,解决了类型不兼容的报错。

如果后续要把Field组件抽离成通用组件,可以用泛型结合FieldPath类型适配任意表单结构:

import { useForm, FieldPath, FieldValues } from 'react-hook-form';

// 通用Field组件,支持任意表单类型
function Field<T extends FieldValues>({ name, register }: { name: FieldPath<T>, register: ReturnType<typeof useForm<T>>['register'] }) {
    return (
        <>
            <input {...register(name)} />
        </>
    );
}

function MyForm () {
    const { handleSubmit, register } = useForm<FormValues>();

    const onSubmit = handleSubmit ((data: FormValues) => {
        console.log({data});
    });
    
    return (
        <form onSubmit={onSubmit}>
            <Field<FormValues> name="name" register={register} />
            <input {...register("name")} placeholder="name" />
            <input {...register("details")} placeholder="details" />
            <input type="submit" />
        </form>
    );
}

type FormValues = {
    name: string;
    details: string;
}

export default MyForm;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 22:52:48