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

fix(react-query): prevent type errors and improve inference for dynamic queries on useQueries, useSuspenseQueries and createQueries #8624

Merged
merged 25 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a0e71f3
fix(react-query): prevent type errors and improve inference for dynam…
gs18004 Feb 8, 2025
a761dc9
fix(react-query): improve type inference for useQueries and useSuspen…
gs18004 Feb 9, 2025
df4aebb
fix(react-query): fix type of queries in useQueries and useSuspenseQu…
gs18004 Feb 9, 2025
30ee20b
refactor: remove meaningless depths
gs18004 Feb 10, 2025
e8d383a
Merge branch 'main' into bug/7974
TkDodo Feb 12, 2025
fdfd8b9
test(react-query): move type only tests
gs18004 Feb 12, 2025
0c007c4
test(react-query): fix type test error
gs18004 Feb 12, 2025
5e0b9e5
fix(vue-query): prevent type errors and improve inference for dynamic…
gs18004 Feb 12, 2025
caf92c2
Merge branch 'main' into bug/7974
TkDodo Feb 12, 2025
fb1b7b9
fix: prevent type errors and improve inference for dynamicqueries
gs18004 Feb 12, 2025
bbf5fde
fix: solid type tests
TkDodo Feb 14, 2025
71f27b6
fix: prevent type errors and improve inference for dynamic queries
gs18004 Feb 14, 2025
76344c2
chore: remove test
TkDodo Feb 14, 2025
fc823a1
Merge branch 'main' into bug/7974
TkDodo Feb 16, 2025
6b91ff0
test(react-query): fix failing type tests
gs18004 Feb 16, 2025
4d5306e
Merge branch 'main' into bug/7974
TkDodo Feb 16, 2025
9d7d7ca
Merge branch 'main' into bug/7974
gs18004 Feb 17, 2025
4e6ffb5
Merge branch 'main' into bug/7974
gs18004 Feb 18, 2025
37c4f3c
Merge branch 'main' into bug/7974
gs18004 Feb 18, 2025
ab45e8b
fix: fix test syntax error
gs18004 Feb 18, 2025
4a85362
test(react-query): remove tests for result[0].data
gs18004 Feb 18, 2025
65bbb85
Merge branch 'main' into bug/7974
gs18004 Feb 19, 2025
083e349
fix: change the result fallback to fix test fail
gs18004 Feb 19, 2025
08db211
Merge branch 'main' into bug/7974
TkDodo Feb 20, 2025
d3cce4c
rollback(angular-query-experimental): restore injectQueries
gs18004 Feb 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions packages/react-query/src/__tests__/useQueries.test-d.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { describe, expectTypeOf, it } from 'vitest'
import { queryKey, sleep } from 'src/__tests__/utils'
import { skipToken } from '..'
import { useQueries } from '../useQueries'
import { queryOptions } from '../queryOptions'
Expand Down Expand Up @@ -141,4 +142,42 @@ describe('UseQueries config object overload', () => {
expectTypeOf(firstResult).toEqualTypeOf<UseQueryResult<number, Error>>()
expectTypeOf(firstResult.data).toEqualTypeOf<number | undefined>()
})

it('should return correct data for dynamic queries with mixed result types', () => {
const key1 = queryKey()
const key2 = queryKey()
const Queries1 = {
get: () =>
queryOptions({
queryKey: key1,
queryFn: async () => {
await sleep(10)
return 1
},
}),
}
const Queries2 = {
get: () =>
queryOptions({
queryKey: key2,
queryFn: async () => {
await sleep(10)
return true
},
}),
}

const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() }))
const result = useQueries({
queries: [...queries1List, { ...Queries2.get() }],
})

expectTypeOf(result).toEqualTypeOf<
[...Array<UseQueryResult<number, Error>>, UseQueryResult<boolean, Error>]
>()

if (result[0]) {
expectTypeOf(result[0].data).toEqualTypeOf<number | boolean | undefined>()
}
})
})
43 changes: 43 additions & 0 deletions packages/react-query/src/__tests__/useSuspenseQueries.test-d.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { describe, expectTypeOf, it } from 'vitest'
import { queryKey, sleep } from 'src/__tests__/utils'
import { skipToken, useSuspenseQueries } from '..'
import { queryOptions } from '../queryOptions'
import type { OmitKeyof } from '..'
Expand Down Expand Up @@ -154,4 +155,46 @@ describe('UseSuspenseQueries config object overload', () => {
expectTypeOf(data).toEqualTypeOf<Data>()
})
})

it('should return correct data for dynamic queries with mixed result types', () => {
const key1 = queryKey()
const key2 = queryKey()

const Queries1 = {
get: () =>
queryOptions({
queryKey: key1,
queryFn: async () => {
await sleep(10)
return 1
},
}),
}
const Queries2 = {
get: () =>
queryOptions({
queryKey: key2,
queryFn: async () => {
await sleep(10)
return true
},
}),
}

const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() }))
const result = useSuspenseQueries({
queries: [...queries1List, { ...Queries2.get() }],
})

expectTypeOf(result).toEqualTypeOf<
[
...Array<UseSuspenseQueryResult<number, Error>>,
UseSuspenseQueryResult<boolean, Error>,
]
>()

if (result[0]) {
expectTypeOf(result[0].data).toEqualTypeOf<number | boolean>()
}
})
})
32 changes: 15 additions & 17 deletions packages/react-query/src/useQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,23 +203,19 @@ export type QueriesResults<
[...TResults, GetUseQueryResult<Head>],
[...TDepth, 1]
>
: T extends Array<
UseQueryOptionsForUseQueries<
infer TQueryFnData,
infer TError,
infer TData,
any
>
>
? // Dynamic-size (homogenous) UseQueryOptions array: map directly to array of results
Array<
UseQueryResult<
unknown extends TData ? TQueryFnData : TData,
unknown extends TError ? DefaultError : TError
>
: {
[K in keyof T]: T[K] extends UseQueryOptionsForUseQueries<
infer TQueryFnData,
infer TError,
infer TData,
any
>
: // Fallback
Array<UseQueryResult>
? UseQueryResult<
unknown extends TData ? TQueryFnData : TData,
unknown extends TError ? DefaultError : TError
>
: GetUseQueryResult<T[number]>
}

export function useQueries<
T extends Array<any>,
Expand All @@ -229,7 +225,9 @@ export function useQueries<
queries,
...options
}: {
queries: readonly [...QueriesOptions<T>]
queries:
| readonly [...QueriesOptions<T>]
| readonly [...{ [K in keyof T]: GetUseQueryOptionsForUseQueries<T[K]> }]
combine?: (result: QueriesResults<T>) => TCombinedResult
subscribed?: boolean
},
Expand Down
32 changes: 15 additions & 17 deletions packages/react-query/src/useSuspenseQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,30 +160,28 @@ export type SuspenseQueriesResults<
[...TResults, GetUseSuspenseQueryResult<Head>],
[...TDepth, 1]
>
: T extends Array<
UseSuspenseQueryOptions<
infer TQueryFnData,
infer TError,
infer TData,
any
>
>
? // Dynamic-size (homogenous) UseQueryOptions array: map directly to array of results
Array<
UseSuspenseQueryResult<
unknown extends TData ? TQueryFnData : TData,
unknown extends TError ? DefaultError : TError
>
: {
[K in keyof T]: T[K] extends UseSuspenseQueryOptions<
infer TQueryFnData,
infer TError,
infer TData,
any
>
: // Fallback
Array<UseSuspenseQueryResult>
? UseSuspenseQueryResult<
unknown extends TData ? TQueryFnData : TData,
unknown extends TError ? DefaultError : TError
>
: GetUseSuspenseQueryResult<T[number]>
}

export function useSuspenseQueries<
T extends Array<any>,
TCombinedResult = SuspenseQueriesResults<T>,
>(
options: {
queries: readonly [...SuspenseQueriesOptions<T>]
queries:
| readonly [...SuspenseQueriesOptions<T>]
| readonly [...{ [K in keyof T]: GetUseSuspenseQueryOptions<T[K]> }]
combine?: (result: SuspenseQueriesResults<T>) => TCombinedResult
},
queryClient?: QueryClient,
Expand Down
40 changes: 40 additions & 0 deletions packages/vue-query/src/__tests__/useQueries.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { describe, expectTypeOf, it } from 'vitest'
import { reactive } from 'vue'
import { sleep } from 'node_modules/@tanstack/query-core/src/utils'
import { skipToken, useQueries } from '..'
import { queryOptions } from '../queryOptions'
import type { OmitKeyof, QueryObserverResult } from '..'
Expand Down Expand Up @@ -219,4 +220,43 @@ describe('UseQueries config object overload', () => {

expectTypeOf(queryCombineWithoutSelect.value).toEqualTypeOf<Array<number>>()
})

it('should return correct data for dynamic queries with mixed result types', () => {
const Queries1 = {
get: () =>
queryOptions({
queryKey: ['key1'],
queryFn: async () => {
await sleep(10)
return 1
},
}),
}
const Queries2 = {
get: () =>
queryOptions({
queryKey: ['key2'],
queryFn: async () => {
await sleep(10)
return true
},
}),
}

const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() }))
const { value: queriesState } = useQueries({
queries: [...queries1List, { ...Queries2.get() }],
})

expectTypeOf(queriesState).toEqualTypeOf<
[
...Array<QueryObserverResult<number, Error>>,
QueryObserverResult<boolean, Error>,
]
>()

expectTypeOf(queriesState[0].data).toEqualTypeOf<
number | boolean | undefined
>()
})
})
36 changes: 19 additions & 17 deletions packages/vue-query/src/useQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,23 +225,19 @@ export type UseQueriesResults<
[...TResults, GetUseQueryResult<Head>],
[...TDepth, 1]
>
: T extends Array<
UseQueryOptionsForUseQueries<
infer TQueryFnData,
infer TError,
infer TData,
any
>
>
? // Dynamic-size (homogenous) UseQueryOptions array: map directly to array of results
Array<
QueryObserverResult<
unknown extends TData ? TQueryFnData : TData,
unknown extends TError ? DefaultError : TError
>
: {
[K in keyof T]: T[K] extends UseQueryOptionsForUseQueries<
infer TQueryFnData,
infer TError,
infer TData,
any
>
: // Fallback
Array<QueryObserverResult>
? QueryObserverResult<
unknown extends TData ? TQueryFnData : TData,
unknown extends TError ? DefaultError : TError
>
: GetUseQueryResult<T[number]>
}

type UseQueriesOptionsArg<T extends Array<any>> = readonly [
...UseQueriesOptions<T>,
Expand All @@ -255,7 +251,13 @@ export function useQueries<
queries,
...options
}: {
queries: MaybeRefDeep<UseQueriesOptionsArg<T>>
queries:
| MaybeRefDeep<UseQueriesOptionsArg<T>>
| MaybeRefDeep<
readonly [
...{ [K in keyof T]: GetUseQueryOptionsForUseQueries<T[K]> },
]
>
combine?: (result: UseQueriesResults<T>) => TCombinedResult
shallow?: boolean
},
Expand Down
Loading