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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 05:07:22