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

如何解决IDE中关于对象属性的TypeScript类型错误

解决TypeScript遍历StoreUnits对象时的索引类型错误

背景

我用React和MobX写了一个自定义Hook,这个Hook接收StoreUnits类型的对象units,同时用useState保存另一个StoreUnits类型的对象currentUnits。在Hook里我会遍历units对象,如果某个属性和currentUnits的对应属性不一致,就调用setter更新currentUnits。

问题

虽然已经明确units和currentUnits都是StoreUnits类型,但IDE中(运行时无异常,仅IDE报错)的currentUnits[key]和units[key]出现类型错误。

错误信息

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'StoreUnits'.
  No index signature with a parameter of type 'string' was found on type 'StoreUnits'.ts(7053)
const currentUnits: StoreUnits

代码 - 自定义Hook

'use client'
import { useState, useEffect } from 'react'
import { autorun } from 'mobx'

type StoreUnits = {
  lengthUnit: 0 | 1 | 2 | 3
  pointForceUnit: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8
  stressUnit: 0 | 1 | 2 | 3
  areaUnit: 0 | 1 | 2
}

const useCurrentUnits = (units: StoreUnits) => {
    const [currentUnits, setCurrentUnits] = useState<StoreUnits>(units)
    
    useEffect(() => {
      autorun(() => {
        for (const [key, value] of Object.entries(units)) {
          if (currentUnits[key] !== units[key]) {
            setCurrentUnits({...units})
            break
          }
        }
      })
    }, [units])
  return {
    currentUnits
  }
}

export default useCurrentUnits

已尝试方案

我试过用currentUnits[key as 'lengthUnit']来消除错误,但这明显不合理,因为key并不总是'lengthUnit'。

解决方案

问题根源是Object.entries(units)返回的key类型为string,TypeScript无法确认这个字符串就是StoreUnits的合法属性名。以下是几种可行的解决方式:

  • 直接断言key类型
    遍历的时候将Object.entries的结果断言为StoreUnits键值对的数组,让TypeScript明确key的合法范围:

    for (const [key, value] of Object.entries(units) as [keyof StoreUnits, StoreUnits[keyof StoreUnits]][]) {
      if (currentUnits[key] !== units[key]) {
        setCurrentUnits({...units})
        break
      }
    }
    
  • 使用类型守卫
    写一个类型守卫函数,严谨校验key是否属于StoreUnits的属性:

    function isStoreUnitsKey(key: string): key is keyof StoreUnits {
      return ['lengthUnit', 'pointForceUnit', 'stressUnit', 'areaUnit'].includes(key)
    }
    
    // 遍历中使用类型守卫
    for (const [key, value] of Object.entries(units)) {
      if (isStoreUnitsKey(key)) {
        if (currentUnits[key] !== units[key]) {
          setCurrentUnits({...units})
          break
        }
      }
    }
    
  • 添加索引签名(不推荐)
    给StoreUnits添加字符串索引签名可以绕过错误,但会丢失类型检查的严谨性,不建议使用:

    type StoreUnits = {
      lengthUnit: 0 | 1 | 2 | 3
      pointForceUnit: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8
      stressUnit: 0 | 1 | 2 | 3
      areaUnit: 0 | 1 | 2
      [key: string]: number // 添加索引签名
    }
    

内容的提问来源于stack exchange,提问作者IdoBa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 16:13:39