I've written a simple function to enhance fetch functionality. I am currently exploring how TypeScript Generics can be utilized to define the Type for 'data' in the return.
const apiFetchData = async (
url: string,
options = {},
): Promise<FetchResponse> => {
try {
const res = await fetch(url, options);
const data = (await res.json()) || null;
const statusCode = res.status;
return {
data,
hasData: !!data,
statusCode,
error: (statusCode !== 200 && true) || false,
errorType: (statusCode !== 200 && 'api') || null,
};
} catch (error) {
return {
data: {
error: error.message,
},
hasData: false,
statusCode: 500,
error: true,
errorType: 'application',
};
}
};
The structure of the FetchResponse type is as follows:
type FetchResponse = {
data: {
[key: string]: {};
error?: string;
};
hasData: boolean;
statusCode: number;
error: boolean | null;
errorType?: 'api' | 'application' | null;
};
If my API response will contain the following format:
type User = {
name: string;
email: string;
}
Then I aim for my FetchResponse to look like this:
type FetchResponse = {
data: User;
hasData: boolean;
statusCode: number;
error: boolean | null;
errorType?: 'api' | 'application' | null;
};
This would allow me to do something similar to the following:
const response = await apiFetchData('URL');
console.log('User name is', response.data.name);
Currently, I use the following approach, which functions but seems lengthy:
type FetchWithUserType = FetchResponse & {
data: {
error?: string;
user?: User;
};
};
and then:
const response: FetchWithUserType = await apiFetchData('URL');
console.log('User name is', response.data.name);
If generics are not the appropriate solution, I welcome assistance in improving this process so I can achieve my objective. The main challenge lies in having VSCode intelligently recognize the content within the returned data instead of being generic and constantly switching between code views.