lukemorales / query-key-factory

A library for creating typesafe standardized query keys, useful for cache management in @tanstack/query
https://www.npmjs.com/package/@lukemorales/query-key-factory
MIT License
1.16k stars 32 forks source link

Taking into account `select` option #69

Closed ruudandriessen closed 1 year ago

ruudandriessen commented 1 year ago

Part of the options in tanstack query is the select property.

We were in the process of moving towards using query-key-factory, however we ran into typing issues since this property isn't being taken into account. Essentially, if select is defined, the ReturnType of select should be used instead of the return type of queryFn. We're using select in order to have cache hits even though data is transformed in different matters for differing use cases.

Example:

const items = createQueryKeys('items', {
    list: {
        queryFn: api.getListOfItems<ItemResponse>(),
        select: (response): MappedType => response.map(someThingThatChangesTheType),
    },
});

The expectation here would be that when using useQuery(items.list) the data property would be of type MappedType. Instead we found it's still `ItemResponse.

If I can get some pointers, I can also attempt a PR myself in order to clean up the types.

lukemorales commented 1 year ago

@ruudandriessen what exactly is your issue? you can have something like this work normally: useQuery({ ...items.list, select: (response) => response.map(someThingThatChangesTheType) }).

Are you trying to create custom hooks with generics? If so, I just released in the past couple of days a utility type TypedUseQueryOptions that should help you achieve that more easily:

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

const items = createQueryKeys('items', {
    list: {
        queryKey: null,
        queryFn: api.getListOfItems<ItemResponse>,
    },
});

const useCustomQuery = <Data = ItemResponse>(options?: TypedUseQueryOptions<typeof items.list, Data>) => {
  return useQuery({ ...options, ...items.list });
}
lukemorales commented 1 year ago

As for including the select option into this library, I think that falls out of the scope of the library for now.

This might be revisited in the future, but I feel like if the idea is to have support for all query options, using something like react-query-kit makes more sense, since you will already have a custom hook generated for you, while this lib purpose is to help you manage all your query keys in one place

ruudandriessen commented 1 year ago

what exactly is your issue?

We were trying to co-locate the select with the query. Which I'm starting to reconsider if it makes sense in the first place. I think for those cases something like react-query-kit indeed makes a lot of sense.

-- Nevertheless - I think the confusion originated from the fact that I didn't get a type error when passing down select into createQueryKeys and it indeed functioned correctly. All that was invalid was the type of data in the result from useQuery. Hence, I presumed it was intended to properly work in this lib.

I realize select (and other options for that matter) isn't really supported. In which case I'd expect the types to disallow passing anything but queryKey/queryFn/contextQueries - but that didn't actually happen due to typescript doesn't have exact types 😢

That means the TLDR is:

I'd say:

lukemorales commented 1 year ago

@ruudandriessen thanks for bringing this to my attention, I've release v1.3.2 that should block select and any other foreign keys from being added

ruudandriessen commented 1 year ago

@ruudandriessen thanks for bringing this to my attention, I've release v1.3.2 that should block select and any other foreign keys from being added

Great! Thanks for the quick response and clarifications @lukemorales 😄