TypeScript中如何使用动态键访问对象属性并解决赋值类型报错?
问题根源
key参数声明为string类型过于宽泛,TypeScript无法确认该值是否为variant对象的合法属性,因此不允许用于索引对象- 输入框返回值固定为
string类型,而variant部分属性为number类型,直接赋值会出现类型不匹配,TypeScript推导不出兼容所有属性的赋值类型因此报错never - 现有代码直接修改原状态对象的引用,不符合React状态不可变的更新原则,可能引发渲染异常
解决方案
第一步:提前定义类型
先为Product和Variant结构声明明确的TS类型,作为类型校验的基础:
interface Variant { id: number; sku: string; price: number; price_reduced: number; size: string; } interface Product { title: string; status: string; tax: boolean; variants: Variant[]; } // 声明状态时指定类型 const [product, setProduct] = useState<Product>(/* 你的初始值 */)
第二步:修改updateVariant实现
调整参数类型约束,增加类型转换逻辑,遵循不可变原则更新状态:
const updateVariant = ( id: number, key: keyof Variant, // 限定key只能是Variant的合法属性 e: React.FormEvent<HTMLInputElement> ) => { const rawValue = e.currentTarget.value; setProduct((prev) => ({ ...prev, variants: prev.variants.map((item) => { if (item.id !== id) return item; // 按属性类型转换输入值 const formattedValue = ['id', 'price', 'price_reduced'].includes(key) ? Number(rawValue) : rawValue; // 返回新对象,不修改原引用 return { ...item, [key]: formattedValue }; }) })); };
额外说明
调整后调用updateVariant时,TypeScript会自动校验传入的key是否合法,如果传入Variant不存在的属性会直接抛出编译错误,从源头避免非法赋值。你之前使用as never的写法相当于强制关闭了TypeScript的类型校验,完全丢失了类型安全,不建议长期使用。
内容的提问来源于stack exchange,提问作者Dawesign
相关产品推荐
相关产品推荐

