React组件泛型类型推断总是报错怎么办?

端木一可 阅读 18

在写一个可复用的表单组件时遇到了类型问题,明明定义了泛型接口,但TypeScript老是提示错误:Type 'string' is not assignable to type 'never'

我尝试这样定义组件:

interface FormProps<T> {
  initialValues: T;
  onSubmit: (data: T) => void;
}

function Form<T>({ initialValues, onSubmit }: FormProps<T>) {
  const [formData, setFormData] = useState(initialValues);
  // ...
  return (
    <form onSubmit={(e) => {
      e.preventDefault();
      onSubmit(formData); // 这里报错
    }}>
    </form>
  );
}

然后这样使用:

type UserFormType = {
  name: string;
  age: number;
};

function App() {
  return (
    <Form
      initialValues={{ name: '', age: 0 }}
      onSubmit={(data) => console.log(data.email)} // 这里居然没报错!
    />
  );
}

奇怪的是,当我在onSubmit里访问不存在的data.email时TypeScript居然没提示,但formData赋值时却提示类型错误。试过给useState添加类型注解:useState(initialValues),但没用,到底哪里出问题了?

我来解答 赞 5 收藏
二维码
手机扫码查看
1 条解答
宇文熙恩
问题出在泛型没有被正确约束,TypeScript推断不出来T的具体类型,导致formData是unknown或者never。

你得强制让泛型从initialValues推导出来,同时给useState加上类型。复制这个:

function Form(props: FormProps) {
const { initialValues, onSubmit } = props;
const [formData, setFormData] = useState(initialValues);

return (
{
e.preventDefault();
onSubmit(formData);
}}>
{/* 假设这里渲染一些字段 */}

);
}


关键是调用的时候要确保泛型能被推导出来。你可以这样用:

function App() {
return (
initialValues={{ name: '', age: 0 }}
onSubmit={(data) => {
console.log(data.name); // OK
console.log(data.email); // 这里现在会报错了!
}}
/>
);
}


注意:如果你写成 initialValues={{} as UserFormType} 或者手动指定泛型 <Form<UserFormType>> 也可以,但最好让TS自动推导。

核心就两点:
1. 给useState加 类型注解
2. 确保initialValues有明确结构让TS能推导

不然TS根本不知道T长什么样,自然后面用data.email也不会报错——因为它认为data是any或者never。
点赞 3
2026-02-09 17:01