I'm having a hard time properly typing a simple useQuery hook.
I am getting the type error "Property 'name' does not exist on type 'never'" on hero.name
. I suspect I need to type HeroData:[]
more specifically but all my attempts of doing so haven't worked. Any help would be appreciated, thank you.
import { useQuery } from "react-query";
import axios from "axios";
interface data {
HeroData: [];
}
function fetchSuperHeroes(): Promise<HeroData> {
return axios.get("http://localhost:4000/superheroes");
}
function RQSuperHeroesPage() {
const { isLoading, data, error } = useQuery({
queryKey: "super-heroes",
queryFn: fetchSuperHeroes,
});
if (isLoading) {
return <h2>Loading...</h2>;
}
if (error instanceof Error) {
return <h2>{error.message}</h2>;
}
return (
<>
<h2>RQ Super Heroes Page</h2>
{data?.data.map((hero) => {
return <div key={hero.name}>{hero.name}</div>;
})}
</>
);
}
export default RQSuperHeroesPage;
I think you're right about the error but there are a few issues with how you're defining the type as well.
interface data {
HeroData: [];
}
^ Here you are setting an array as the type for HeroData
. TypeScript will infer this type as type HeroData = Array<never>
which basically means it can only ever be an empty array. This is your main problem.
function fetchSuperHeroes(): Promise<HeroData> {
return axios.get("http://localhost:4000/superheroes");
}
^ The second issue is that you are only passing HeroData
into your ReturnType
definition for your fetcher. This should have actually given you an error in your IDE since HeroData
does not exist outside of the data
interface. Further to that, passing HeroData
as the ReturnType
doesn't satisfy the way you are parsing the data in your code -- data.data
.
For future reference, you can grab a type from an interface using the bracket notation property accessor
type SomePropType = SomeInterface['some_prop'];
// e.g.
type HData = data['HeroData']
Now, with that aside here's an approach that should work for you:
// Define your Hero type
type Hero = {
name: string;
// other hero props here...
}
// Define your HeroData interface
interface HeroData {
// Define data as an array of type Hero
data: Hero[];
}
// Use your HeroData interface here so the return matches the
// expected shape `data.data`
function fetchSuperHeroes(): Promise<HeroData> {
return axios.get("http://localhost:4000/superheroes");
}
Hope this helps!