TypeScript给React.useState加类型注解后展开赋值报错如何解决
错误根因
你在调用React.useState<IInterval>()时没有传入初始值,此时TypeScript会自动推导selectedInterval的类型为IInterval | undefined。当你展开undefined时,TypeScript无法保证最终生成的对象包含IInterval要求的必填属性name(会被推导为可选的string | undefined类型),因此触发类型不匹配错误。
你收到的错误提示中文含义如下:
类型“{ id: number; name?: string | undefined; }”的参数不能赋给类型“SetStateAction<IInterval | undefined>”的参数。 不能将类型“{ id: number; name?: string | undefined; }”分配给类型“IInterval”。 属性“name”的类型不兼容。 不能将类型“string | undefined”分配给类型“string”。 不能将类型“undefined”分配给类型“string”。 TS2345
解决方案
下面按适用场景给出不同解法:
方案1:给useState设置符合类型要求的初始值
如果业务逻辑允许初始化时就有默认值,直接给useState传入符合IInterval结构的初始值即可,这是最推荐的无侵入解法:
// 初始值的属性完全匹配IInterval的必填要求 const [selectedInterval, setSelectedInterval] = React.useState<IInterval>({ name: '', id: 0 });
此时selectedInterval永远为IInterval类型,展开后不会出现属性缺失的问题,原onChange代码无需修改即可正常运行。
方案2:更新时兜底处理undefined场景
如果业务必须要求初始值为undefined,更新时可以对prev值做兜底,保证最终生成的对象完全符合IInterval类型要求:
<SomeElement onChange={(e) => setSelectedInterval(prev => ({ // prev为undefined时兜底空对象,同时断言为IInterval保证类型匹配 ...(prev ?? {} as IInterval), id: parseInt(+e.value) }))} />
如果你的业务逻辑要求只有selectedInterval已经被赋值过才能更新id,也可以加判断分支:
<SomeElement onChange={(e) => { if (!selectedInterval) return setSelectedInterval({ ...selectedInterval, id: parseInt(+e.value) }) }} />
方案3:修改接口属性为可选(仅当业务允许时使用)
如果业务逻辑里name本身就允许为空,直接修改IInterval的结构即可:
interface IInterval { name?: string, // 改为可选属性 id: number }
内容的提问来源于stack exchange,提问作者TugboatCaptain
相关产品推荐
相关产品推荐

