query icon indicating copy to clipboard operation
query copied to clipboard

remove overloads

Open TkDodo opened this issue 2 years ago • 1 comments

context

useQuery and friends have many overloads in TypeScript - different ways how the function can be invoked. As an example, let's look at useQuery. You can call it in three different ways:

useQuery(queryKey, queryFn, options)
useQuery(queryKey, options)
useQuery(options)

The queryKey is the only required property. The queryFn is optional because you might have defined it globally. If you use the syntax where you only pass one object in, the queryKey is also required.

Not only is this tough to maintain, type wise, it also requires a runtime check to see which type the first and the second parameter are to correctly create options. Internally, we only work with one options object.

Further, we started to add more overloads for features that are only doable with overloads. For example, if you pass initialData, the return type of data will not contain undefined. Because initialData can also be a function, we need another 3 overloads for each possibility to call useQuery, resulting in 9 total overloads.

The useQuery.ts file has 140 lines of code - only 3 of which are actual JavaScript.

Other functions suffer from the same problem, and overloads are also not consistent. For example, queryCache.findAll has overloads, but mutationCache.findAll does not.

proposal

  • remove all overloads and only allow all functions to be called with a single signature - one object

detailed changes

- useQuery(key, fn, options)
+ useQuery({ queryKey, queryFn, ...options })
// ⬆️ queryKey must be required

- useInfiniteQuery(key, fn, options)
+ useInfiniteQuery({ queryKey, queryFn, ...options })
// ⬆️ queryKey must be required

- useMutation(fn, options)
+ useQuery({ mutationFn, ...options })

- useIsFetching(key, filters)
+ useIsFetching({ queryKey, ...filters })

- useIsMutating(key, filters)
+ useIsMutating({ mutationKey, ...filters })
- queryClient.isFetching(key, filters)
+ queryClient.isFetching({ queryKey, ...filters })

- queryClient.ensureQueryData(key, fn, options)
+ queryClient.ensureQueryData({ queryKey, queryFn, ...options })
// ⬆️ queryKey must be required

- queryClient.getQueriesData(key, filters)
+ queryClient.getQueriesData({ queryKey, ...filters })

- queryClient.setQueriesData(key, updater, filters, options)
+ queryClient.setQueriesData({ queryKey, ...filters }, updater, options)

- queryClient.removeQueries(key, filters)
+ queryClient.removeQueries({ queryKey, ...filters })

- queryClient.resetQueries(key, filters, options)
+ queryClient.resetQueries({ queryKey, ...filters }, options)

- queryClient.cancelQueries(key, filters, options)
+ queryClient.cancelQueries({ queryKey, ...filters }, options)

- queryClient.invalidateQueries(key, filters, options)
+ queryClient.invalidateQueries({ queryKey, ...filters }, options)

- queryClient.refetchQueries(key, filters, options)
+ queryClient.refetchQueries({ queryKey, ...filters }, options)

- queryClient.fetchQuery(key, fn, options)
+ queryClient.fetchQuery({ queryKey, queryFn, ...options })

- queryClient.prefetchQuery(key, fn, options)
+ queryClient.prefetchQuery({ queryKey, queryFn, ...options })

- queryClient.fetchInfiniteQuery(key, fn, options)
+ queryClient.fetchInfiniteQuery({ queryKey, queryFn, ...options })

- queryClient.prefetchInfiniteQuery(key, fn, options)
+ queryClient.prefetchInfiniteQuery({ queryKey, queryFn, ...options })

- queryCache.find(key, filters)
+ queryCache.find({ queryKey, ...filters })
// ⬆️ queryKey must be required
// `exact` could be omitted from possible filters and always set to `true` !

- queryCache.findAll(key, filters)
+ queryCache.findAll({ queryKey, ...filters })

TkDodo avatar Dec 23 '22 09:12 TkDodo

Working on it 🫡

Mamoanwar97 avatar Dec 24 '22 22:12 Mamoanwar97

Hello, I wanted to make sure of something

queryClient.fetchQuery({ queryKey, queryFn, ...options })
queryClient.fetchInfiniteQuery({ queryKey, queryFn, ...options })

queryClient.prefetchQuery({ queryKey, queryFn, ...options })
queryClient.prefetchInfiniteQuery({ queryKey, queryFn, ...options })
queryCache.findAll({ queryKey, ...filters })

In these 5, is the queryKey required?

Mamoanwar97 avatar Dec 26 '22 23:12 Mamoanwar97

Also, the PR will be big 😅 should I split it into multiple PRs? or just organize the commits messages?

image

I am almost there 😅 just need to remove the useMutation/useIsMutating overloads and It will be done

Mamoanwar97 avatar Dec 27 '22 00:12 Mamoanwar97

In these 5, is the queryKey required?

it's required for fetch and fetchInfinite, but not for findAll. In findAll, it's just one possible filter (part of the QueryFilters type). If you use QueryFilters as-is, it's fine.

Also, the PR will be big 😅 should I split it into multiple PRs? or just organize the commits messages?

One PR will be fine, thank you

TkDodo avatar Dec 27 '22 06:12 TkDodo