Search code examples
typescriptuse-statereact-typescript

React Typescript: Element implicitly has an 'any' type because index expression is not of type 'number'


I am trying one make simple voting app. My app works fine. I have decided to make my app in Typescript. I am beginner level in Typescript.

I pass arrays of string to the app component then. I create a sort function where it will get most voted and attached my string which get most voted.

But The problem is I am getting typescript error when I am attaching my string with mostVoted sort function.

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

Also I create a state I used any. I don't know what I should define the state instead of any .

This is the state

 const [votes, setVotes] = useState<any>({
    // what should I define my state instead of any
    0: 0,
    1: 0,
    2: 0,
    3: 0,
    4: 0,
    5: 0,
  });

This is my all code

import React, { useState } from "react";
import ReactDOM from "react-dom";

const anecdotes: string[] = [
  "If it hurts, do it more often",
  "Adding manpower to a late software project makes it later!",
  "The first 90 percent of the code accounts for the first 90 percent of the development time...The remaining 10 percent of the code accounts for the other 90 percent of the development time.",
  "Any fool can write code that a computer can understand. Good programmers write code that humans can understand.",
  "Premature optimization is the root of all evil.",
  "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.",
];

interface Props {
  title?: string;
  anecdote?: string;
  numVotes?: number;
}

const Anecdote = ({ title, anecdote, numVotes }: Props) => (
  <>
    <h1>{title}</h1>
    <div>{anecdote}</div>
    <div>Has {numVotes} votes</div>
  </>
);

interface AppProps {
  anecdotes: string[];
}

const App = ({ anecdotes }: AppProps) => {
  const [selected, setSelected] = useState<number>(0);
  const [votes, setVotes] = useState<any>({
    // what should I define my state instead of any
    0: 0,
    1: 0,
    2: 0,
    3: 0,
    4: 0,
    5: 0,
  });

  const mostVoted = Object.keys(votes).sort((a, b) => votes[b] - votes[a])[0]; // Element implicitly has an 'any' type because index expression is not of type 'number'.
  console.log(Object.keys(votes).sort((a, b) => votes[b] - votes[a]));

  const getRandomIndex = () => Math.floor(Math.random() * anecdotes.length);

  const handleNextAnecdote = () => {
    let idx = getRandomIndex();
    while (idx === selected) {
      idx = getRandomIndex();
    }
    setSelected(idx);
  };

  const addVote = () => {
    setVotes({
      ...votes,
      [selected]: votes[selected] + 1,
    });
  };

  return (
    <>
      <Anecdote
        title={"Anecdote of the day"}
        anecdote={anecdotes[selected]}
        numVotes={votes[selected]}
      />
      <button onClick={handleNextAnecdote}>Next anecdote</button>
      <button onClick={addVote}>Vote</button>
      <Anecdote
        title={"Anecdote with most votes"}
        anecdote={anecdotes[mostVoted]} // In here I am getting typescript Error.
        numVotes={votes[mostVoted]}
      />
    </>
  );
};

ReactDOM.render(<App anecdotes={anecdotes} />, document.getElementById("root"));

I share my code in codesand-box


Solution

  • The problem is that anecdotes is an array which requires a number to index it, but mostVoted is not a number, because the keys of an object are always strings (see Is there any way to use a numeric type as an object key?). This results in the error you get.

    To resolve the issue you can parse mostVoted to an int and use that:

    const mostVoted = parseInt(Object.keys(votes).sort((a, b) => votes[b] - votes[a])[0], 10);
    

    Regarding the type of your state you can write it as

    const [votes, setVotes] = useState<{[key: string]: number}>({
      0: 0,
      1: 0,
      2: 0,
      3: 0,
      4: 0,
      5: 0,
    });