TypeScript动态访问对象属性:React状态更新类型报错解决方案
问题描述
我有多个数据输入字段:
<input type="text" placeholder={`title`} onChange={(e) => change(`title`,e)} /> <input type="text" placeholder={`description`} onChange={(e) => change(`description`,e)} /> ...
同时为这些字段维护一个统一的状态:
type Iinfo = { title: string, description: string, stars: number } const [info, setInfo] = useState<Iinfo | null>(null)
我希望用户在输入框中输入内容时,仅更新状态中对应的字段,于是编写了如下change函数:
const change = (title: string,e: React.ChangeEvent<HTMLInputElement>) => { setInfo ({...info,[title]:e.target.value}) }
但TypeScript抛出了类型错误,请问如何在不创建如下索引签名接口的前提下实现需求?
interface A { [key: string]: string; [key: number]: string; }
解决方案
约束字段名的合法范围:把
change函数的第一个参数类型从string改为keyof Iinfo,让TypeScript只允许传入Iinfo中定义的字段名,避免非法字段导致的类型错误:const change = (field: keyof Iinfo, e: React.ChangeEvent<HTMLInputElement>) => { // 后续逻辑 }处理初始状态为null的情况:因为
info可能是null,直接解构会引发问题,先给默认初始值兜底:const change = (field: keyof Iinfo, e: React.ChangeEvent<HTMLInputElement>) => { const currentInfo = info ?? { title: '', description: '', stars: 0 }; // 后续逻辑 }匹配字段的类型差异:
e.target.value是字符串类型,但stars是number类型,需要针对性做类型转换:const change = (field: keyof Iinfo, e: React.ChangeEvent<HTMLInputElement>) => { const currentInfo = info ?? { title: '', description: '', stars: 0 }; let value: string | number = e.target.value; // 针对stars字段转数字,空输入设为0避免NaN if (field === 'stars') { value = Number(e.target.value) || 0; } setInfo({ ...currentInfo, [field]: value }); }可选:更严谨的泛型写法:用泛型让TypeScript自动推断字段对应的类型,进一步提升类型安全:
const change = <K extends keyof Iinfo>(field: K, e: React.ChangeEvent<HTMLInputElement>) => { const currentInfo = info ?? { title: '', description: '', stars: 0 }; const value = field === 'stars' ? Number(e.target.value) || 0 : e.target.value; setInfo({ ...currentInfo, [field]: value as Iinfo[K] }); }
以上方案无需添加索引签名,既能保证TypeScript的类型校验通过,又能实现仅更新对应字段的需求。
内容的提问来源于stack exchange,提问作者Rei
相关产品推荐
相关产品推荐

