I want to display the products after fetching them and everything works fine but I have some error with TS in the destructuring statement.
Here is my fetching function:
export async function fetchAllProducts() {
try {
const res = await axios.get(url);
const data = res.data;
return {
data
}
} catch(err) {
if(err instanceof AxiosError)
return {
error: err.message
}
}
}
And then I use it in a server component:
export default async function StorePage() {
const { data, error }: Products = await fetchAllProducts(); //the problem is in this line (data and error are underlined)
return (
<section className='section'>
<div className='section__inner'>
<h4 className='section__title'>Products</h4>
{error && <span>{error}</span>}
{!data && !error && <span>loading...</span>}
<div className='section__content products-container'>
{!error && data && data?.length > 0 && data.map((product: ProductProps) => <ProductCard key = {product.id} {...product}/>)}
</div>
</div>
</section>
)
}
When I destructure I get this error:
Type ‘{ data: any; error?: undefined; } | { error: string; data?:
undefined; } | undefined’ is not assignable to type ‘Products’. Type
‘undefined’ is not assignable to type ‘Products’.
Here are my types:
export type Products = {
data: ProductProps[] | null;
error: string | undefined;
}
export type ProductProps = {
id: string;
title: string;
category: string;
description: string;
image: string;
price: number;
rating: {
rate: number,
count: number
}
}
So, I was wondering if the problem was connected to the fetch function, should I add types there or is there another issue?
>Solution :
In
export type Products = {
data: ProductProps[] | null;
error: string | undefined;
}
the data property has either to be a ProductProps[] or null. But in case of an error during fetchAllProducts
const { data, error }: Products = await fetchAllProducts();
the result of fetchAllProducts will be
{
error: string
}
ie, no data, ie data == undefined which is not allowed in a valid instance of the Products type … Change the return value in case of an exception to
return {
error: err.message,
data: null
}
Also in your Products, the error is a mandatory property, ie it can have the value of undefined but it has to exist. If you want it to be optional, define your Products as follows
export type Products = {
data: ProductProps[] | null;
error?: string;
}
See this Playground to see the difference.
Furthermore, you should also consider, what happens if err is not an AxiosError. Then your fetchAllProducts won’t return anything and you will try to destructure a value of undefined, which will throw a runtime error.