TypeScript中为自定义useForm Hook传递初始值报错求助
解决自定义useForm Hook的TypeScript类型问题
你这段代码的核心问题在于联合类型的类型窄化限制。当你把initialState定义为FormTypes(也就是IForm1 | IForm2)时,useForm返回的values类型也是这个联合类型。TypeScript无法确定当前的values到底是IForm1还是IForm2,所以直接访问values.word会报错——因为如果values是IForm1的话,它根本没有word属性。
要让useForm能复用在不同表单上,同时保持TypeScript的类型安全,应该用泛型来替代联合类型。这样每个调用useForm的地方都可以传入对应表单的类型,TypeScript会自动推断并确保类型正确。
修改后的完整代码示例:
import { useState } from 'react'; // 定义各个表单的接口 interface IForm1 { name?: string; description?: string; } interface IForm2 { word?: string; } // 用泛型T来接收任意表单类型,限制T为对象类型 const useForm = <T extends object>(initialState: T) => { const [values, setValues] = useState<T>(initialState); // 可以添加通用的表单输入处理函数,方便复用 const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => { const { name, value } = e.target; setValues(prev => ({ ...prev, [name]: value })); }; return { values, setValues, handleChange }; }; const WorkComponent = () => { // 这里可以手动指定泛型参数为IForm2,TypeScript会确保values的类型匹配 const { values, handleChange } = useForm<IForm2>({ word: '' }); // 现在访问values.word完全不会有类型错误 console.log(values.word); return ( <input name="word" value={values.word || ''} onChange={handleChange} /> ); };
关键说明:
- 泛型
<T extends object>让useForm可以适配任意结构的表单对象,不再局限于预先定义的几个接口。 - 调用时可以手动指定泛型参数(比如
useForm<IForm2>(...)),也可以让TypeScript自动从initialState推断类型——比如useForm({ name: '' })会自动识别这是IForm1类型的表单。 - 添加的
handleChange是通用的表单处理函数,能适配大部分输入控件,进一步提升Hook的复用性。
内容的提问来源于stack exchange,提问作者ProxNN
相关产品推荐
相关产品推荐

