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

React Hook Form Control类型不匹配:自定义组件库跨项目报错

自定义组件库集成React Hook Form与Material UI的类型冲突问题

我开发了一个自定义组件库,其中包含一个通过Controller集成Material UI与React Hook Form的组件,代码如下:

import * as React from "react";
import { TextField } from "@mui/material";
import { useController } from "react-hook-form";
import { FieldValues } from "react-hook-form/dist/types";
import { TextFieldProps } from "@mui/material/TextField/TextField";
import ReactHookFormCommonProps from "./ReactHookFormCommonProps";

type JmfFormTextFieldPropsInternal = TextFieldProps;

export type JmfFormTextFieldProps<
    TFieldValues extends FieldValues,
    TContext
> = JmfFormTextFieldPropsInternal &
    ReactHookFormCommonProps<TFieldValues, TContext>;

/**
 * 集成了react-hook-form的TextField组件。<br>
 * 其他属性会直接传递给TextField组件
 */
export const JmfFormTextField = <TFieldValues extends FieldValues, TContext>({
    name,
    control,
    errors,
    ...other
}: JmfFormTextFieldProps<TFieldValues, TContext>) => {
    const { field } = useController({ name, control });
    return (
        <TextField
            error={!!errors[name]}
            helperText={`${errors[name]?.message ?? ""}`}
            variant="outlined"
            {...other}
            {...field}
        />
    );
};

React Hook Form通用Props定义

React Hook Form的可复用Props定义在独立文件中:

import { Control, FieldValues } from "react-hook-form/dist/types";
import { Path } from "react-hook-form";
import { FieldErrors } from "react-hook-form/dist/types/errors";

export default interface ReactHookFormCommonProps<
    TFieldValues extends FieldValues,
    TContext
> {
    /**
     * react-hook-form字段名称
     */
    name: Path<TFieldValues>;
    /**
     * react-hook-form的Control对象
     */
    control: Control<TFieldValues, TContext>;
    /**
     * react-hook-form的错误对象,用于校验提示
     */
    errors: FieldErrors<TFieldValues>;
}

Storybook本地使用示例

在组件库项目中,通过Storybook创建的示例使用完全正常,无任何错误:

import * as React from "react";
import { useForm } from "react-hook-form";
import { JmfFormTextField } from "./JmfFormTextField";
import { ComponentMeta, ComponentStory } from "@storybook/react";

export default {
    title: "JmfFormTextField",
    component: JmfFormTextField,
} as ComponentMeta<typeof JmfFormTextField>;

interface FormInputs {
    email: string;
}

export const Primary: ComponentStory<typeof JmfFormTextField> = () => {
    const {
        control,
        formState: { errors },
    } = useForm<FormInputs>({
        defaultValues: {
            email: "",
        },
    });

    return (
        <JmfFormTextField
            control={control}
            name="email"
            errors={errors}
            type="email"
            label="Email"
            variant="outlined"
        />
    );
};

跨项目引入时的TypeScript错误

但将该组件库作为依赖引入其他项目时,会出现如下TypeScript错误;若使用npm link,项目甚至无法启动:

TS2322: Type 'import("C:/Users/adamo/WorkSpace/multima/taxguru/frontend/node_modules/react-hook-form/dist/types/form").Control<LoginFormValueTypes, any>' is not assignable to type 'import("C:/Users/adamo/WorkSpace/multima/jmf/frontend/node_modules/react-hook-form/dist/types/form").Control<LoginFormValueTypes, any>'.   Types of property '_updateFieldArray' are incompatible.     Type 'import("C:/Users/adamo/WorkSpace/multima/taxguru/frontend/node_modules/react-hook-form/dist/types/form").BatchFieldArrayUpdate' is not assignable to type 'import("C:/Users/adamo/WorkSpace/multima/jmf/frontend/node_modules/react-hook-form/dist/types/form").BatchFieldArrayUpdate'.       Types of parameters 'updatedFieldArrayValues' and 'updatedFieldArrayValues' are incompatible.         Type 'Partial<FieldArray<TFieldValues, TFieldArrayName>>[] | undefined' is not assignable to type 'Partial<FieldArray<TFieldValues, ArrayPath<TFieldValues>>>[] | undefined'.           Type 'Partial<FieldArray<TFieldValues, TFieldArrayName>>[]' is not assignable to type 'Partial<FieldArray<TFieldValues, ArrayPath<TFieldValues>>>[]'.             Type 'Partial<FieldArray<TFieldValues, TFieldArrayName>>' is not assignable to type 'Partial<FieldArray<TFieldValues, ArrayPath<TFieldValues>>>'.               Type 'keyof FieldArray<TFieldValues, ArrayPath<TFieldValues>>' is not assignable to type 'keyof FieldArray<TFieldValues, TFieldArrayName>'.                 Type 'string | number | symbol' is not assignable to type 'keyof FieldArray<TFieldValues, TFieldArrayName>'.                   Type 'string' is not assignable to type 'keyof FieldArray<TFieldValues, TFieldArrayName>'.                     Type 'string' is not assignable to type 'never'.                       Type 'keyof FieldArray<TFieldValues, ArrayPath<TFieldValues>>' is not assignable to type 'never'.                         Type 'string | number | symbol' is not assignable to type 'never'.                           Type 'string' is not assignable to type 'never'.  ReactHookFormCommonProps.d.ts(13, 5): The expected type comes from property 'control' which is declared here on type 'IntrinsicAttributes & JmfFormTextFieldProps<LoginFormValueTypes, any>'

解决方法

1. 配置peerDependencies

将react-hook-form从组件库的dependencies移至peerDependencies,指定兼容的版本范围,确保主项目和组件库使用同一版本的依赖:

{
  "peerDependencies": {
    "react-hook-form": "^7.0.0"
  }
}

2. 修正类型导入路径

避免从react-hook-form/dist/types这类深层路径导入类型,直接从包根目录导入,保证类型定义一致:

// 替换原来的导入方式
import { Control, FieldValues, Path, FieldErrors } from "react-hook-form";

3. 清理重复依赖

  • 使用npm link时,在主项目中执行npm dedupe合并重复依赖
  • 若问题仍存在,删除组件库和主项目的node_modules及package-lock.json,重新执行npm install

内容的提问来源于stack exchange,提问作者Adam Ostrožlík

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 21:05:20