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 Error when using useQueries with results returning different types, generated from an array #7974

Open
todor-a opened this issue Aug 29, 2024 · 3 comments
Labels
bug Something isn't working help wanted Extra attention is needed types

Comments

@todor-a
Copy link
Contributor

todor-a commented Aug 29, 2024

Describe the bug

I want to use useQueries to fetch x queries every time, and another y queries, whose count is not known at compile time.

Here is a short example (playground below):

export const useThings = () => {
    const foos = [1, 2, 3].map(() => ({ ...FooQueries.get() }));

    return useQueries({
        queries: [...foos, { ...BarQueries.get(), }],
    });
};

There is a type error that says:

The type 'QueryKey' is 'readonly' and cannot be assigned to the mutable type 'string[]'

Your minimal, reproducible example

https://tsplay.dev/mq2d2W

Steps to reproduce

use useQueries with a variable count of queries that have different return type than other queries

Expected behavior

Expected to be able to pass an array of queries with variable length to useQueries, along with other queries with different return type.

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

  • MacOS

Tanstack Query adapter

None

TanStack Query version

5.52.1

TypeScript version

5.5.4

Additional context

Edit: I tinkered a bit more with this and it appears that the issue is with the queryOptions function. Here is the full error:

Type '{ queryKey: string[] & { [dataTagSymbol]: number; }; enabled?: Enabled<number, Error, number, string[]> | undefined; staleTime?: StaleTime<number, Error, number, string[]> | undefined; ... 25 more ...; maxPages?: number | undefined; }' is not assignable to type 'UseQueryOptionsForUseQueries<unknown, Error, unknown, QueryKey>'.
  Type '{ queryKey: string[] & { [dataTagSymbol]: number; }; enabled?: Enabled<number, Error, number, string[]> | undefined; staleTime?: StaleTime<number, Error, number, string[]> | undefined; ... 25 more ...; maxPages?: number | undefined; }' is not assignable to type 'OmitKeyof<UseQueryOptions<unknown, Error, unknown, QueryKey>, "placeholderData">'.
    Types of property 'enabled' are incompatible.
      Type 'Enabled<number, Error, number, string[]> | undefined' is not assignable to type 'Enabled<unknown, Error, unknown, QueryKey> | undefined'.
        Type '(query: Query<number, Error, number, string[]>) => boolean' is not assignable to type 'Enabled<unknown, Error, unknown, QueryKey> | undefined'.
          Type '(query: Query<number, Error, number, string[]>) => boolean' is not assignable to type '(query: Query<unknown, Error, unknown, QueryKey>) => boolean'.
            Types of parameters 'query' and 'query' are incompatible.
              Type 'Query<unknown, Error, unknown, QueryKey>' is not assignable to type 'Query<number, Error, number, string[]>'.
                Types of property 'queryKey' are incompatible.
                  The type 'QueryKey' is 'readonly' and cannot be assigned to the mutable type 'string[]'.ts(2322)

Edit 2: If all queries return the same type of result, it works.

@TkDodo TkDodo added bug Something isn't working types labels Aug 29, 2024
@TkDodo
Copy link
Collaborator

TkDodo commented Aug 29, 2024

different return types generally work, I think this is rather an issue with queryOptions. If we remove queryOptions, it also works. playground.

Or rather, a combination of the two:

  • queryOptions for BarQueries returns the type UseQueryOptions<boolean, Error, boolean, string[]>, so the TQueryKey type parameter is inferred to be string[]
  • useQueries infers the type to be UseQueryOptionsForUseQueries<unknown, Error, unknown, QueryKey>. Here, the TQueryKey type parameter is inferred to QueryKey, which is our upper bound, and that is readonly unknown[]

So it seems the readonly here makes all the difference.

But even if we get rid of that by making our keys of type QueryKey, we get a different error:

Type 'QueryFunction<unknown, QueryKey, never>' is not assignable to type 'QueryFunction<number, QueryKey, never>'.
  Type 'unknown' is not assignable to type 'number'.(2322)

This is again because inference of UseQueryOptionsForUseQueries, where data falls back to unknown.

Thinking about it some more - I don't think variadic queries of different types is something that we can infer / support. For variadic queries, they have to be the same type. Static queries (tuples) of different types are supported.

In your example, ideally the last element in the result array would be typed as bar, and all the others as foo. But I think this is way to complex to achieve, which is why we fallback to unknown, and that then doesn't really work with queryOptions.

I think you have to do manual type annotations for this one. Like, what should the data type of useThings be? number | boolean - a union of what all queries can return, or just unknown?

@todor-a
Copy link
Contributor Author

todor-a commented Aug 29, 2024

I agree that typing this will be way too complex.

To answer your question, I think that the type can be number | boolean[], if the call looks like this (the spread is at the end):

export const useThings = () => {
    const foos = [1, 2, 3].map(() => ({ ...FooQueries.get() }));

    return useQueries({
        queries: [{ ...BarQueries.get() }, ...foos],
    });
};

@TkDodo
Copy link
Collaborator

TkDodo commented Sep 6, 2024

if you want to make that work, please take a stab at it.

@TkDodo TkDodo added the help wanted Extra attention is needed label Sep 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed types
Projects
None yet
Development

No branches or pull requests

2 participants