Tomas Gomez Belcastro
Tomas Gomez Belcastro

Reputation: 47

Typescript error (2345) when pushing element to array of elements(React js)

I'm pretty new to Typescript and I was trying to migrate a component I had on Reactjs to typescript. This component is supposed to receive a number from 0-10 as a prop and according to that number populate an array with stars components which are icons I imported from React icons. once the array is populated is then rendered by the component. but when I try to push those elements to the Array typescript throws an error as if those elements were not of type Element neither Jsx. The only way I found it to work was by setting

let starsArray: Element[] | any = [];

but my idea was not to leave anything as "any" type;

import React, { useState, useEffect } from "react";
import { BsStarFill } from "react-icons/bs";

interface PropsInterface {
  stars: number;
  big?: boolean;
}

const Stars: React.FC<PropsInterface> = ({ stars, big }) => {
  const [array, setArray] = useState<Element[]>([]);

  useEffect(() => {
    let starsArray: Element[] = [];
    let starsAmount: number = Math.round(stars) / 2; //gets rating from props and turns it into integer divided by two (ratings were 1-10 and we needed 1-5 stars);

    for (let i = 0; i < 5; i++) {
      //goes throught 1-5 and if the rating amount is higher or equal on each iteration it pushes a filled star component to  starsArray, else it pushes an empty star
      if (starsAmount > i) {
        starsArray.push(<BsStarFill className="star--filled" key={i} />);
      } else {
        starsArray.push(<BsStarFill className="star--unfilled" key={i} />);
      }
    }

    setArray(starsArray);
  }, []);

  return (
    <div className={big ? "stars --bigstars" : "stars"}>
      {Object.values(array).map((each) => each)}
    </div>
  );
};

export default Stars;



these where the lines showing the error with a red underline

(<BsStarFill className="star--unfilled" key={i} />)
(<BsStarFill className="star--filled" key={i} />)

these is the complete error :

Argument of type 'JSX.Element' is not assignable to parameter of type 'Element'. Type 'ReactElement<any, any>' is missing the following properties from type 'Element': attributes, classList, className, clientHeight, and 123 more.ts(2345)

I would really appreciate some help here, thank you !

Upvotes: 1

Views: 881

Answers (2)

Tomas Gomez Belcastro
Tomas Gomez Belcastro

Reputation: 47

UPDATE: After trying different solutions I found myself fixing the error by setting array and StarsArray as an array of ReactNodes type;

Starsarray: ReactNode[] = [];

A more general explanation: TypeScript expects you to explicitly define the type of the array elements. The array elements type you declared must match the type TypeScript expects to see. Here is a simple example:

interface ISomething {
    arr: string[]
}

// Somewhere in a class a method uses ISomething interface.
public someMethod(): ISomething['arr'] {
    // Note, if you omit ": ISomething['arr']" in the line below
    // you would face ts2345 error when you push a string into the array later.
    const localArray: ISomething['arr'] = [];
    localArray.push('somestring');
    return localArray;
}

Upvotes: 1

jsonderulo
jsonderulo

Reputation: 1494

So the compiler is saying that <BsStarFill /> is a JSX.Element. But you have declared the array and star arrays as Element[] which is a differnt type

let starsArray: JSX.Element[] = [];

const [array, setArray] = useState<JSX.Element[]>([]);

change these to the proper types and it should compile

When to use JSX.Element vs ReactNode vs ReactElement?

this contains more information about jsx element and react element types

Upvotes: 0

Related Questions