React与TypeScript编辑对象属性:已做检查仍遇Type 'string'不可赋值给'never'错误
问题原因
TypeScript无法通过typeof newNewFam[attributeToSet] === 'string'这个运行时检查,推断出attributeToSet对应的Family属性类型确实是string。因为attributeToSet是keyof Family的联合类型,即便当前属性值是string,TypeScript也没法确定该key在Family定义里的类型就是string,所以赋值时会判定类型不兼容,抛出Type 'string' is not assignable to type 'never'错误。
解决方案
方法1:自定义类型守卫(推荐)
写一个类型谓词函数,明确判断传入的key对应的Family属性是string类型,帮TypeScript缩小类型范围:
// 筛选出Family中属性为string的key类型 type FamilyStringKeys = { [K in keyof Family]: Family[K] extends string ? K : never }[keyof Family]; // 类型守卫函数 function isFamilyStringKey(key: keyof Family): key is FamilyStringKeys { return typeof ({} as Family)[key] === 'string'; } // 修改后的familySetter const familySetter = (newValue: string, attributeToSet: keyof Family) => { setNewFamily((currNewFam) => { if (!currNewFam) return; const newNewFam: Family = { ...currNewFam }; if (isFamilyStringKey(attributeToSet)) { newNewFam[attributeToSet] = newValue; // 类型匹配,无错误 } return newNewFam; }); };
方法2:泛型约束限制输入
直接在函数参数层面,限制attributeToSet只能是Family中属性为string的key,从源头避免类型不匹配:
type FamilyStringKeys = { [K in keyof Family]: Family[K] extends string ? K : never }[keyof Family]; const familySetter = <K extends FamilyStringKeys>(newValue: string, attributeToSet: K) => { setNewFamily((currNewFam) => { if (!currNewFam) return; const newNewFam: Family = { ...currNewFam }; newNewFam[attributeToSet] = newValue; // 类型安全,无需额外检查 return newNewFam; }); };
方法3:类型断言(不推荐,仅确定类型时使用)
如果能100%确定当前属性是string类型,可以用类型断言强制赋值,但会跳过TypeScript的类型检查,存在风险:
const familySetter = (newValue: string, attributeToSet: keyof Family) => { setNewFamily((currNewFam) => { if (!currNewFam) return; const newNewFam: Family = { ...currNewFam }; if (typeof newNewFam[attributeToSet] === 'string') { // 断言该属性为string类型 (newNewFam[attributeToSet] as string) = newValue; } return newNewFam; }); };
内容的提问来源于stack exchange,提问作者bsellier
相关产品推荐
相关产品推荐

