You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript中如何使用动态键访问对象属性并解决赋值类型报错?

问题根源

  1. key参数声明为string类型过于宽泛,TypeScript无法确认该值是否为variant对象的合法属性,因此不允许用于索引对象
  2. 输入框返回值固定为string类型,而variant部分属性为number类型,直接赋值会出现类型不匹配,TypeScript推导不出兼容所有属性的赋值类型因此报错never
  3. 现有代码直接修改原状态对象的引用,不符合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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 12:24:02