Reputation: 47
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
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
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