skip to Main Content

Code:

export const useAllUsers = <T extends UserResponseDto>(
  select?: (data: UserResponseDto[]) => T
) =>
  useQuery<UserResponseDto[], ErrorResponse, T, string[]>({
    queryKey: [QueryClientKeys.GET_ALL_USERS],
    queryFn: async () => {
      const response = await ApiService.getAllUsers();
      return response.data;
    },
    select: select,
    staleTime: Infinity,
    cacheTime: Infinity,
    retry: false,
  });

Is it possible to define the selector for a useQuery hook to return a generic type as above?

With this setup, whenever I use the useAllUsers hook without passing the select function, I get UserResponseDto as the data type and not UserResponseDto[].

2

Answers


  1. You are telling useQuery that the data type returned from it is of type T extends UserResponseDto, so in no case could that be UserResponseDto[] since UserResponseDto[] does not extend UserResponseDto.

    Do you really mean <T extends UserResponseDto>? Because <T extends UserResponseDto[]> makes more sense to me and would solve the issue.

    If <T extends UserResponseDto> is what you want you could do <T extends unknown = UserResponseDto[]>, to allow select to return any type, but in the same time tell the compiler that if select doesn’t exist, the data type is UserResponseDto[].

    Login or Signup to reply.
  2. your generic is defined as:

    T extends UserResponseDto

    However, select can return anything – it shouldn’t be bound to be something that is "assignable to" UserResponseDto. But what you’d want to express is that T should default to UserResponseDto[] for cases where you don’t provide a select function, because select is where useQuery infers the type of T from.

    That means you need:

    T = UserResponseDto[]

    instead.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search