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

如何为React自定义useForm Hook实现TypeScript泛型类型推导

TypeScript 类型适配实现方案

要实现useForm自动根据传入初始值推导返回inputs的精确类型,只需要给Hook添加泛型约束即可,不需要在调用时手动重复声明类型。

完整带类型的Hook实现

import { useState, ChangeEvent } from 'react';

// 定义泛型T,约束为普通对象类型,TS会自动从入参推导T的具体结构
const useForm = <T extends Record<string, any>>(initial: T) => {
  const [inputs, setInputs] = useState<T>(initial);

  // 表单输入变更方法,覆盖常用表单元素类型
  const onChange = (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
    const { name, value, type } = e.target;
    // 针对数字输入做类型转换,避免数字字段被转为字符串
    const finalValue = type === 'number' ? Number(value) : value;
    setInputs(prev => ({
      ...prev,
      [name]: finalValue
    }));
  };

  // 重置表单为初始值
  const resetForm = () => setInputs(initial);

  // 清空表单内容
  const clearInputs = () => {
    const emptyState = Object.fromEntries(
      Object.entries(initial).map(([key, val]) => [key, typeof val === 'number' ? 0 : ''])
    ) as T;
    setInputs(emptyState);
  };

  return { inputs, onChange, resetForm, clearInputs };
};

实现说明

  • 泛型参数T会在调用Hook时,由TS自动根据传入的initial参数推导精确结构,不需要调用方手动传入泛型
  • 给useState指定泛型T后,返回的inputs会完全继承初始值的字段类型,不会出现any类型的问题
  • onChange方法内置了数字类型转换逻辑,只要给对应输入框设置type="number",就能保证数字字段的类型一致性

调用效果验证

原有业务代码不需要任何修改,就能获得精准的类型提示:

// inputs自动推导为 { name: string; age: number; city: string }
const { inputs, onChange: handleChange, resetForm } = useForm({ name: "", age: 25, city: "Amsterdam" });

其他场景调用也会自动适配类型:

// inputs自动推导为 { distance: number; hours: number; speed: number }
const { inputs } = useForm({ distance: 40, hours: 2, speed: 5 });

如果你使用了自定义表单输入组件,可以根据实际组件的事件参数类型,调整onChange方法的入参类型即可。

内容的提问来源于stack exchange,提问作者Justin van Dijk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:54:27