I am trying to write a custom useQuery hook to fetch a list of exercises. The hook should also accept an optional select function. In the case where the optional select function is provided, the type of the data that the useQuery
hook returns should be of type number
. When the select function is not provided, the type of should be PaginatedExerciseInfo<Exercises>
.
I am having trouble implementing this in a way that doesn't upset typescript. Currently, when I call the hook without passing a select function to it (shown below), the data it returns is always of type number
.
const { data: exercises, isError, isLoading, refetch } = useGetExercises<Exercise>(muscleGroup);
As I haven't passed a select to it, I was hoping in this case exercises would be of type PaginatedExerciseInfo<Exercises> | undefined
So far, I have tried to write the hook like this
export const getExercises = async (muscleGroup: MuscleGroup, page: number, perPage: number) => {
const { data } = await axios.get(`http://localhost:8000/exercises/${muscleGroup}?page=${page}&per_page=${perPage}&sort=-date`);
return data;
};
export const useGetExercises = <Exercises extends string>(muscleGroup: MuscleGroup, select?: (data: PaginatedExerciseInfo<Exercises>) => number) => {
const { page, perPage } = useContext(PaginationContext);
return useQuery<
PaginatedExerciseInfo<Exercises>,
unknown,
typeof select extends undefined ? PaginatedExerciseInfo<Exercises> : number
>({
queryKey: [muscleGroup, 'exercises', page, perPage],
queryFn: () => getExercises(muscleGroup, page, perPage),
select: select
});
};
Hovering over the useQuery
function, I can see that the conditional type I've written for the third generic passed into useQuery is always interpreted as undefined
.
Is there a way to achieve what I want to achieve using typescript?
select?
means (roughly speaking)something|undefined
which always extends undefined. This is all that can be known at compile time – Oligocene