question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItĀ collects links to all the places you might be looking at while hunting down a tough bug.

And, if youā€™re still stuck at the end, weā€™re happy to hop on a call to see how we can help out.

Custom useQuery typing

See original GitHub issue

Hello šŸ‘‹

Iā€™m trying to build some reusable useQuery functions so that I donā€™t have to declare them every time I want to use them. To do so, and to avoid having a lot of type repetition Iā€™ve also created some custom typing so that I donā€™t need to declare the TError type all the time.

To build my custom typing, I just tried to replicate the usage of types of useQuery in this codebase. It is defined as if follows:

import {
 UseQueryOptions,
 UseQueryReturnType,
} from "@tanstack/vue-query"
import { AxiosError } from "axios"

import { ErrorAPIResponse } from "@/types/model/APIResponse"

export type CustomUseQueryOptions<
 TArgs,
 TData,
 TError = Error | AxiosError<ErrorAPIResponse>,
> = Omit<
 UseQueryOptions<
   TData,
   TError,
   TData,
   TArgs extends void ? string[] : (string | TArgs)[]
 >,
 "queryKey" | "queryFn"
>

export type CustomQueryHook<
 TArgs,
 TData,
 TError = Error | AxiosError<ErrorAPIResponse>,
> = TArgs extends void
 ? (
     options?: CustomUseQueryOptions<TArgs, TData, TError>,
   ) => UseQueryReturnType<TData, TError>
 : (
     args: TArgs,
     options?: CustomUseQueryOptions<TArgs, TData, TError>,
   ) => UseQueryReturnType<TData, TError>

and one example of its usage in a custom useQuery:

import { useContext } from "@nuxtjs/composition-api"
import { useQuery } from "@tanstack/vue-query"

import { ApiPaths } from "@/enums"
import { SuccessAPIResponse } from "@/types/model/APIResponse"
import { User } from "@/types/model/User"
import { CustomQueryHook } from "@/types/vue-query"

type ApiResponse = SuccessAPIResponse<User[]>
export type UsersQueryResponse = User[]

export const queryKey = "UsersQuery"

export const useUsersQuery: CustomQueryHook<void, UsersQueryResponse> = (
  options,
) => {
  const { $axios } = useContext()

  return useQuery(
    [queryKey],
    async () => {
      const { data } = await $axios.get<ApiResponse>(ApiPaths.GET_USERS)

      return data.data
    },
    options,
  )
}

This approach is working with vue-query@1.25.0 but failing with @tanstack/vue-query@4.12.0, causing the following error:

Type '(options: CustomUseQueryOptions<void, UsersQueryResponse, Error | AxiosError<ErrorAPIResponse>> | undefined) => UseQueryReturnType<...>' is not assignable to type '(options?: CustomUseQueryOptions<void, UsersQueryResponse, Error | AxiosError<ErrorAPIResponse>> | undefined) => UseQueryReturnType<...>'.
  Type 'UseQueryReturnType<UsersQueryResponse, Error | AxiosError<ErrorAPIResponse>>' is not assignable to type 'UseQueryReturnType<UsersQueryResponse, Error | AxiosError<ErrorAPIResponse>, QueryObserverResult<UsersQueryResponse, Error | AxiosError<...>>>'.
    Type 'UseQueryReturnType<UsersQueryResponse, Error | AxiosError<ErrorAPIResponse>>' is not assignable to type 'ToRefs<Readonly<QueryObserverLoadingResult<UsersQueryResponse, Error | AxiosError<ErrorAPIResponse>>>> & { ...; }'.
      Type 'UseQueryReturnType<UsersQueryResponse, Error | AxiosError<ErrorAPIResponse>>' is not assignable to type 'ToRefs<Readonly<QueryObserverLoadingResult<UsersQueryResponse, Error | AxiosError<ErrorAPIResponse>>>>'.
        Types of property 'data' are incompatible.
          Type 'Ref<undefined> | Ref<UsersQueryResponse>' is not assignable to type 'Ref<undefined>'.
            Type 'Ref<UsersQueryResponse>' is not assignable to type 'Ref<undefined>'.
              Type 'UsersQueryResponse' is not assignable to type 'undefined'.ts(2322)

The issue seems to be around the QueryObserverResult generic types, but I couldnā€™t find a reason for it to not work. Am I missing something in my custom type definition or is it an issue with the types themselves?

Thanks!

Issue Analytics

  • State:closed
  • Created a year ago
  • Reactions:2
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
DamianOsipiukcommented, Dec 22, 2022

@Alexis2004 I have looked at your example, basically when you use initialData you should use UseQueryDefinedReturnType instead of UseQueryReturnType.

1reaction
Alexis2004commented, Nov 6, 2022

Hello!

I also faced the same problem in my project.

The only way Iā€™ve been able to get around this problem is to use an explicit cast on the result of calling the useQuery function:

export function useProduct(): UseQueryReturnType<ProductDTO, unknown> {
  const options: UseQueryOptions<ProductDTO, unknown> = {
    queryKey: [...],
    queryFn: () => ...
  };

  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore
  return useQuery(options) as UseQueryReturnType<ProductDTO, unknown>;
}

In runtime, this code works properly, that is, the problem is precisely in the type declarations.

By the way, the problem is reproduced not only on the latest version of vue-query@2.0.0-beta.12, but also on his @tanstack/vue-query@4.14.1.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Custom hooks with QueryOptions & TypeScript #1195 - GitHub
Type 'string' is not assignable to type 'Post'. I don't know how to set up the options types to get the same result...
Read more >
Custom useQuery Hook - TinyHouse: A Fullstack React ...
In this lesson, we'll create our very own custom useQuery Hook that will ... Just like we've done already, we'll make our Hook...
Read more >
Creating a useQuery hook with typescript - matthewburfield
useState accepts a what TypeScript calls a ā€œGenericā€ type as a parameter, ... This is where creating a custom hook comes into play!...
Read more >
TypeScript with Apollo Client - Apollo GraphQL Docs
This function enables us to type the variables that go into our React hooks, along with the results from those hooks. useQuery. Below...
Read more >
useQuery used in custom hook returns a response with type ...
I have the following custom hook called useFocusRefetchQuery type Props = Parameters<typeof useQuery>; const useFocusRefetchQueryĀ ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found