Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type inference is not compatible with query #59

Closed
baeharam opened this issue Apr 30, 2023 · 13 comments · Fixed by #65 or #67
Closed

Type inference is not compatible with query #59

baeharam opened this issue Apr 30, 2023 · 13 comments · Fixed by #65 or #67
Assignees

Comments

@baeharam
Copy link

baeharam commented Apr 30, 2023

@lukemorales Thanks for your great library!

I'm using this package to manage query keys effectively, but when I have to use custom options to inject useQuery or something like this, it is not "easily" compatible with types of @tanstack/react-query.

For example,

const useCustomQuery = (options?: UseQueryOptions<DataType>) => {
  // TYPE ERROR
  return useQuery({ ...options, ...queryKey.someQuery });
}

In above case, type error is occurred so I have to use specify query key type of this package.

const useCustomQuery = (options?: UseQueryOptions<DataType, unknown, unknown, typeof queryKey.someQuery.queryKey>) => {
  return useQuery({ ...options, ...queryKey.someQuery });
}

It solves type issue, but I think is awkward to specify 3 types with UseQueryOptions. I want more simple solution like below.

const useCustomQuery = (options?: UseQueryOptions<typeof queryKey.someQuery>) => {
  return useQuery({ ...options, ...queryKey.someQuery });
}

It may be related to issue #48 and #40.
I hope it could be solved elegantly :) Thanks for reading! 😄

[Reproduction]

스크린샷 2023-04-30 오후 10 13 07

https://codesandbox.io/s/type-error-of-query-key-factory-49so1x?file=/src/App.tsx

@joeyfigaro
Copy link

Any movement on this? @baeharam how have you worked around this issue? I'm having the same problem.

@lukemorales
Copy link
Owner

@joeyfigaro @baeharam sorry, I completely missed this issue with a lot that's going on my personal life. I'll take a look and try to come up with a fix in the next upcoming days

@lukemorales
Copy link
Owner

lukemorales commented Jun 15, 2023

@joeyfigaro @baeharam just released v1.3.0 that exposes a new type TypedUseQueryOptions for you to use in these cases:

import { TypedUseQueryOptions } from '@lukemorales/query-key-factory'

const useCustomQuery = (options?: TypedUseQueryOptions<typeof queryKey.someQuery>) => {
  return useQuery({ ...options, ...queryKey.someQuery });
}

As a bonus tip: since you're allowing all options (and possibly the select option that will change the data type), always create your hooks with a generic:

import { TypedUseQueryOptions } from '@lukemorales/query-key-factory'

const useCustomQuery = <Data = SomeQueryResult>(options?: TypedUseQueryOptions<typeof queryKey.someQuery, Data>) => {
  return useQuery({ ...options, ...queryKey.someQuery });
}

// in your component

const { data } = useCustomQuery()
//       ^? SomeQueryResult


const { data } = useCustomQuery({ select: data => data.name })
//       ^? string

@baeharam
Copy link
Author

@lukemorales Thanks for your solution, but it has 2 limitations.

  1. I have to specify type of "selector". Originally, query infers selected data type with select field. But TypedUseQueryOptions needs "selector" data type with generic. In practice, selected type is too complex so defining selector type everytime is very nervous.

  2. When querykey object is generated by function, it causes type error like below.

const queryKey = createQueryKeys("test", () => ({
  test1Query: (params: SomeParamsType) => ({ queryKey: ..., queryFn: ... })
});

In above case, I cannot use TypedUseQueryOptions.

These 2 problems are very important so I hope it could be solved ASAP. Thanks! 😄

@lukemorales
Copy link
Owner

@baeharam can you explain exactly why 1 is very nervous? Even with UseQueryOptions, if you don't specify a generic for the selected data at the function level, when you use select in your options param, it will not reflect that you're returning a different shape than the query function return type.

As for number 2, that's just typescript syntax: TypedUseQueryOptions<ReturnType<typeof queryKey['test1Query']>>

@lukemorales
Copy link
Owner

I can see if providing a function that returns queryKey and queryFn for 2 it will also handle internally, but that's improved DX, not a problem at all, that's just using plain typescript

@lukemorales
Copy link
Owner

@baeharam can you explain exactly why 1 is very nervous? Even with UseQueryOptions, if you don't specify a generic for the selected data at the function level, when you use select in your options param, it will not reflect that you're returning a different shape than the query function return type.

As for number 2, that's just typescript syntax: TypedUseQueryOptions<ReturnType<typeof queryKey['test1Query']>>

@baeharam here's what I'm talking about: https://codesandbox.io/s/type-error-of-query-key-factory-forked-38yxsq?file=/src/App.tsx

You can see on line 34 that typescript is complaining about the different data being returned on select prop and if you hover over selectedData on line 33, you will see that the type is still TestResponse

@baeharam
Copy link
Author

@lukemorales

Sry, I misunderstood that original selector type inference of query. Your answer is right for number 2. But as for number 1, Returntype<typeof queryKey.testQuery> causes type error 😢

image

Reproduction: https://codesandbox.io/s/type-error-of-query-key-factory-forked-j32rwr?file=/src/App.tsx

If I did something wrong, plaese tell me. Thanks!

@lukemorales
Copy link
Owner

@baeharam your example has a small mistake on the queryFn declaration because it's returning directly the fetch invocation instead of a function that returns the promise. However, even fixing that, typescript was understanding the types were too strict and not compatible when the query keys were dynamic generated for some unknown reason 🤷🏻
Because of that, I just released a new patch with loosen types (and you don't need to use ReturnType anymore) that should fix the issue

@baeharam
Copy link
Author

@lukemorales Thanks for your quick work. It works very well 😄

But, I need this kind of utility type with useInfiniteQuery and useMutation 😢
Sorry for bothering...

@lukemorales
Copy link
Owner

@baeharam I can work on the useInfiniteQuery options today, but for useMutation I'm gonna hold off for now because createMutationKeys type inference is broken for now so I'm not pursuing any improvements there before I can fix it

@baeharam
Copy link
Author

@lukemorales Oh, I understood! Then, can you add type for useInfiniteQuery options?

@joeyfigaro
Copy link

@lukemorales I completely missed your responses here–thank you so much for the quick turnaround on this. I'm going to give the new release a shot this evening! Do you have a tip jar anywhere for your work?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants