TypeScript泛型Input自定义钩子报错:string无法赋值给SetStateAction<T>
修复泛型useInput钩子的类型错误
错误原因
input元素的e.target.value始终是string类型,但泛型T可以是任意类型(比如number),直接将string赋值给SetStateAction<T>会触发类型不匹配的错误。原非泛型版本虽然限定了string|number,但其实也存在隐式类型转换的隐患,泛化后TypeScript的类型检查更严格,暴露了这个问题。
解决方案
方案一:限制泛型为string/number,自动转换类型
如果你的钩子只需要支持string和number类型,可以给泛型添加约束,并根据初始值的类型自动转换input值:
import { useState, useCallback, Dispatch, SetStateAction } from 'react'; type InputReturn<T extends string | number> = readonly [ T, (e: React.ChangeEvent<HTMLInputElement>) => void, Dispatch<SetStateAction<T>>, ]; export function useInput<T extends string | number>(initialValue: T): InputReturn<T> { const [value, setValue] = useState(initialValue); const handler = useCallback((e: React.ChangeEvent<HTMLInputElement>) => { const inputVal = e.target.value; // 根据初始值类型转换输入值 const processedVal = typeof initialValue === 'number' ? (inputVal === '' ? 0 : Number(inputVal)) // 空字符串转0,可按需调整 : inputVal; setValue(processedVal as T); }, [initialValue]); return [value, handler, setValue] as const; }
方案二:传入转换函数,支持任意类型
如果需要支持更复杂的类型(比如boolean、自定义枚举),可以让调用者传入一个转换函数,将input的string值转为目标类型T:
import { useState, useCallback, Dispatch, SetStateAction } from 'react'; type InputReturn<T> = readonly [ T, (e: React.ChangeEvent<HTMLInputElement>) => void, Dispatch<SetStateAction<T>>, ]; export function useInput<T>(initialValue: T, transform: (input: string) => T): InputReturn<T> { const [value, setValue] = useState(initialValue); const handler = useCallback((e: React.ChangeEvent<HTMLInputElement>) => { setValue(transform(e.target.value)); }, [transform]); return [value, handler, setValue] as const; }
使用示例:
// 处理number类型 const [age, handleAgeChange, setAge] = useInput(18, (val) => Number(val) || 0); // 处理boolean类型 const [isEnabled, handleEnabledChange, setIsEnabled] = useInput(false, (val) => val === 'true');
内容的提问来源于stack exchange,提问作者Jho
相关产品推荐
相关产品推荐

