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

React Hook Form动态设置错误时TypeScript类型报错问题

解决React Hook Form中setError的TypeScript类型错误

问题核心是Object.keys()返回的类型是string[],而setError的第一个参数要求是具体的表单字段联合类型("companyName" | "addressLine"),TypeScript无法自动推断key属于这个联合类型,所以需要手动做类型收窄或断言。

步骤1:定义正确的字段联合类型

直接用keyof从错误对象或表单类型中推导合法字段的联合类型,比自定义Unionize更简洁:

// 方式1:直接声明联合类型
type FormField = "companyName" | "addressLine";

// 方式2:从错误对象类型自动推导(更灵活,修改错误对象时无需手动更新类型)
const errors = {
  "companyName": "Error for companyName",
  "addressLine": "Error for addressLine"
} as const;
type FormField = keyof typeof errors;

步骤2:修复setError的类型问题

有两种常用方案:

方案一:类型断言(简单直接)

将key断言为FormField类型,适合你能确定errors的所有键都是合法表单字段的场景:

Object.keys(errors).forEach((key) => {
  const fieldKey = key as FormField;
  if (fields.some((field) => field === fieldKey)) {
    setError(fieldKey, {
      type: 'custom',
      message: errors[key]
    });
  }
});

方案二:类型守卫(更安全)

编写类型守卫函数,在运行时验证key是否属于合法字段,同时让TypeScript自动收窄类型:

function isFormField(key: string): key is FormField {
  return ['companyName', 'addressLine'].includes(key);
}

Object.keys(errors).forEach((key) => {
  if (isFormField(key) && fields.some((field) => field === key)) {
    setError(key, {
      type: 'custom',
      message: errors[key]
    });
  }
});

为什么你的Unionize类型无效?

你定义的Unionize返回的是一个对象类型(比如{companyName: "companyName", addressLine: "addressLine"}),而不是你需要的字段联合类型。正确的联合类型应该直接用keyof T,比如:

type Props = keyof { companyName: string; addressLine: string };
// Props 等价于 "companyName" | "addressLine"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 11:22:40