TypeScript泛型使用报错:'not assignable'问题求助
解决useInput Hook中SetStateAction类型不匹配问题
你遇到的错误根源是:TypeScript编译阶段无法通过typeof init的运行时判断,自动缩小泛型T的具体类型,导致setInput接收的参数类型与期望的SetStateAction<T>不兼容。以下是两种简洁的修复方案,无需拆分两个独立函数:
方案一:类型断言快速修复
直接在每个分支中通过类型断言告诉TypeScript当前赋值类型符合泛型T的约束,同时优化数字类型的转换逻辑:
import { useState } from "react"; type useInputT<T> = { value: T; onChange: (e: React.ChangeEvent<HTMLInputElement>) => void; }; export default function useInput<T extends string | number>(init: T): useInputT<T> { const [input, setInput] = useState<T>(init); function onChange(e: React.ChangeEvent<HTMLInputElement>): void { switch (typeof init) { case "string": setInput(e.target.value as T); break; case "number": // 处理空输入或非数字内容,避免NaN进入状态 const num = parseInt(e.target.value, 10); setInput(isNaN(num) ? 0 : num as T); break; } } return { value: input, onChange }; }
方案二:类型守卫增强类型安全性
如果需要更严谨的类型推断,可以自定义类型守卫函数,让TypeScript精确识别分支中的T类型:
import { useState } from "react"; type useInputT<T> = { value: T; onChange: (e: React.ChangeEvent<HTMLInputElement>) => void; }; // 自定义类型守卫,缩小T的类型范围 function isString<T>(val: T): val is T & string { return typeof val === "string"; } function isNumber<T>(val: T): val is T & number { return typeof val === "number"; } export default function useInput<T extends string | number>(init: T): useInputT<T> { const [input, setInput] = useState<T>(init); function onChange(e: React.ChangeEvent<HTMLInputElement>): void { if (isString(init)) { setInput(e.target.value as T); } else if (isNumber(init)) { const num = parseInt(e.target.value, 10); setInput(isNaN(num) ? 0 : num as T); } } return { value: input, onChange }; }
额外优化建议
如果是数字类型的输入,建议将<input>的type设为"number",使用valueAsNumber直接获取数字值,避免字符串转数字的潜在问题:
const inputNumber = useInput<number>(1); return ( <input type="number" value={inputNumber.value} onChange={inputNumber.onChange} /> );
对应的onChange分支修改为:
case "number": const num = e.target.valueAsNumber; setInput(isNaN(num) ? 0 : num as T); break;
内容的提问来源于stack exchange,提问作者joraeune
相关产品推荐
相关产品推荐

