【问题标题】:Typescript won't let me access property of an object using bracket notation打字稿不会让我使用括号表示法访问对象的属性
【发布时间】:2021-05-01 23:20:23
【问题描述】:

我有以下接口:

interface IAnswersCount {
  nintendo: number;
  microsoft: number;
  sony: number;
}

interface IState {
  counter: number;
  questionId: number;
  question: string;
  answerOptions: AnswerType[];
  answer: string;
  answersCount: IAnswersCount;
  result: string;
}

以及功能组件内部的状态,如下所示:

 const [state, setState] = React.useState<IState>({
    counter: 0,
    questionId: 1,
    question: '',
    answerOptions: [],
    answer: '',
    answersCount: {
      nintendo: 0,
      microsoft: 0,
      sony: 0,
    },
    result: '',
  });

在代码中的某处,我试图动态访问answersCount 属性的嵌套属性之一。我的做法是这样的:

const doSomething = (answer: string): void => {

// other things happen here
   const value = state.answerOptions[answer as keyof IAnswersCount]
}

无论我如何编写代码,我都无法摆脱以下错误:

Element implicitly has an 'any' type because index expression is not of type 'number'.

我无法弄清楚我做错了什么,非常感谢任何帮助。

【问题讨论】:

  • state.answerOptions的类型是AnswerType[],所以是一个数组。为什么要尝试使用字符串键访问它? answer as keyof IAnswersCount 的类型将是 nintendo | microsoft | sony,将其用作 answerOptions 数组的键是没有意义的。如果您想根据答案访问选项,您必须重新考虑您的模型,可能使用映射/对象文字。
  • 您的意思是写state.answersCount[answer] 而不是state.answerOptions[answer]
  • @robertgr991 哦,完全。当然它不起作用,我试图访问错误的属性。我实际上想定位answersCount。我的错。谢谢!
  • 顺便说一下,使用 useState 设置一个完整的状态对象并不是最好的做法。您想将每个属性分解为每个属性的 useState 调用,或者在此处使用 reducer。
  • 在状态中使用对象是完全可以接受的,尤其是当对象内的属性被链接时。例如,属性a 和属性b 需要计算属性c. 由于状态是异步的,有3 个单独的状态来管理这些属性意味着不能保证当属性c 重新计算时@987654338 @ 和 b 是最新的。不需要使用 reducer,但可能更容易理解。

标签: javascript reactjs typescript types


【解决方案1】:

您正在索引错误的状态属性:state.answerOptions(它是一个数组)而不是 state.answersCount

我认为你的意思是:

const doSomething = (answer: string): void => {
  // other things happen here
  const value = state.answersCount[answer as keyof IAnswersCount]
}

或者,没有断言:

const doSomething = (answer: keyof IAnswersCount): void => {
  // other things happen here
  const value = state.answersCount[answer]
}

【讨论】:

    【解决方案2】:

    有两个问题:

    1. 您应该为“答案”使用更窄的类型
    2. 我认为您想使用answersCount 而不是answerOptions,因为在您的示例中answerOptionsAnswerType 的数组,而不是具有字符串属性的对象
    const doSomething = (answer: keyof IAnswersCount): void => {
    
       // other things happen here
       const value = state.answersCount[answer];
    }
    

    如果您确实打算使用answersOptions,请分享AnswerType 的类型。

    【讨论】:

      【解决方案3】:

      你需要映射你的密钥,我编辑你的界面:

      interface IAnswersCount {
        [key: string]: number,
        nintendo: number;
        microsoft: number;
        sony: number;
      }
      
      // [key: string]: number
      // is not a new property, is a map access definition
      
      

      【讨论】:

      • 恐怕 any 违背了使用 Typescript 的目的。
      • 看,我编辑你的界面,注意第一行
      猜你喜欢
      • 1970-01-01
      • 2016-04-16
      • 1970-01-01
      • 2015-03-31
      • 2020-10-25
      • 2022-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多