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

React TypeScript中react-hook-form TS2345类型不匹配错误求助

解决React TypeScript中react-hook-form的TS2345类型错误

问题根源

从props中提取的name被TypeScript推断为string类型,但register函数要求的是SignUpFields接口的具体键名("firstName" | "lastName" | "email" | "password" | "location"),类型不匹配导致报错。

修复步骤及代码

1. 给组件添加泛型约束,明确字段类型

将InputElement改为泛型组件,让它适配SignUpFields的任意键,同时精准约束name、rules和error的类型:

import { InputHTMLAttributes } from "react";
import { UseFormRegister, FieldError, RegisterOptions } from "react-hook-form";

interface SignUpFields {
  firstName: string;
  lastName: string;
  email: string;
  password: string;
  location: string;
}

// 用泛型K约束name必须是SignUpFields的键
interface InputElementProps<K extends keyof SignUpFields> 
  extends Omit<InputHTMLAttributes<HTMLInputElement>, "name"> {
  label?: string;
  labelClasses?: string;
  register: UseFormRegister<SignUpFields>;
  rules: RegisterOptions<SignUpFields, K>;
  error?: FieldError;
  name: K; // 明确name是SignUpFields的键类型
}

export function InputElement<K extends keyof SignUpFields>({
  label,
  labelClasses,
  register,
  rules,
  error,
  name, // 直接解构name,不用从props里间接取
  ...props
}: InputElementProps<K>) {
  return (
    <div className="mt-6">
      {label && (
        <label
          htmlFor={props.id}
          className={`block text-primary text-sm font-medium font-montserrat leading-6 ${labelClasses}`}
        >
          {label}
        </label>
      )}
      <input
        {...props}
        {...register(name, rules)}
        className="mt-2 mb-1 bg-transparent active:bg-transparen focus:bg-transparent block w-full rounded-xl   border-2 border-primary px-4 py-2 font-montserrat text-lg text-white placeholder:text-white sm:text-sm sm:leading-6"
      />
      {error && (
        <p className="text-white text-xs font-montserrat mt-1 italic">
          {error.message}
        </p>
      )}
    </div>
  );
}

2. 父组件使用无需修改

原父组件的调用方式保持不变,TypeScript会自动推断K的类型:

<InputElement
  id="First Name"
  name="firstName"
  type="text"
  label="First Name"
  register={register}
  rules={{ required: "First name is required." }}
  error={errors.firstName}
/>

关键修改点说明

  • 用Omit<InputHTMLAttributes<HTMLInputElement>, "name">覆盖原生name的string类型,替换为K extends keyof SignUpFields,确保name只能是SignUpFields的有效键。
  • 直接解构name参数,避免从props间接取值导致的类型丢失。
  • 将rules的类型从FieldValues改为RegisterOptions<SignUpFields, K>,让校验规则和对应字段的类型严格匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 09:22:56