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
相关产品推荐
相关产品推荐

