@tanstack/vue-query 5.40.0 → 5.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/legacy/index.cjs +3 -0
- package/build/legacy/index.cjs.map +1 -1
- package/build/legacy/index.d.cts +1 -0
- package/build/legacy/index.d.ts +1 -0
- package/build/legacy/index.js +2 -0
- package/build/legacy/index.js.map +1 -1
- package/build/legacy/infiniteQueryOptions.cjs +33 -0
- package/build/legacy/infiniteQueryOptions.cjs.map +1 -0
- package/build/legacy/infiniteQueryOptions.d.cts +21 -0
- package/build/legacy/infiniteQueryOptions.d.ts +21 -0
- package/build/legacy/infiniteQueryOptions.js +8 -0
- package/build/legacy/infiniteQueryOptions.js.map +1 -0
- package/build/legacy/useQueries.cjs.map +1 -1
- package/build/legacy/useQueries.d.cts +9 -14
- package/build/legacy/useQueries.d.ts +9 -14
- package/build/legacy/useQueries.js.map +1 -1
- package/build/modern/index.cjs +3 -0
- package/build/modern/index.cjs.map +1 -1
- package/build/modern/index.d.cts +1 -0
- package/build/modern/index.d.ts +1 -0
- package/build/modern/index.js +2 -0
- package/build/modern/index.js.map +1 -1
- package/build/modern/infiniteQueryOptions.cjs +33 -0
- package/build/modern/infiniteQueryOptions.cjs.map +1 -0
- package/build/modern/infiniteQueryOptions.d.cts +21 -0
- package/build/modern/infiniteQueryOptions.d.ts +21 -0
- package/build/modern/infiniteQueryOptions.js +8 -0
- package/build/modern/infiniteQueryOptions.js.map +1 -0
- package/build/modern/useQueries.cjs.map +1 -1
- package/build/modern/useQueries.d.cts +9 -14
- package/build/modern/useQueries.d.ts +9 -14
- package/build/modern/useQueries.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/infiniteQueryOptions.test-d.ts +111 -0
- package/src/__tests__/queryClient.test-d.ts +132 -0
- package/src/__tests__/queryClient.test.ts +17 -0
- package/src/__tests__/queryOptions.test-d.ts +125 -0
- package/src/__tests__/test-utils.ts +0 -10
- package/src/__tests__/useInfiniteQuery.test-d.tsx +84 -0
- package/src/__tests__/useInfiniteQuery.test.ts +32 -0
- package/src/__tests__/useMutation.test-d.tsx +74 -0
- package/src/__tests__/useQueries.test-d.ts +145 -0
- package/src/__tests__/useQuery.test-d.ts +228 -0
- package/src/index.ts +5 -0
- package/src/infiniteQueryOptions.ts +94 -0
- package/src/useQueries.ts +18 -36
- package/src/__tests__/queryClient.type.test.ts +0 -174
- package/src/__tests__/queryOptions.types.test.ts +0 -170
- package/src/__tests__/useInfiniteQuery.types.test.tsx +0 -106
- package/src/__tests__/useMutation.types.test.tsx +0 -98
- package/src/__tests__/useQueries.types.test.ts +0 -176
- package/src/__tests__/useQuery.types.test.ts +0 -282
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { describe, expectTypeOf, it } from 'vitest'
|
|
2
|
+
import { reactive } from 'vue-demi'
|
|
3
|
+
import { useQuery } from '../useQuery'
|
|
4
|
+
import { queryOptions } from '../queryOptions'
|
|
5
|
+
import { simpleFetcher } from './test-utils'
|
|
6
|
+
import type { OmitKeyof } from '..'
|
|
7
|
+
import type { UseQueryOptions } from '../useQuery'
|
|
8
|
+
|
|
9
|
+
describe('initialData', () => {
|
|
10
|
+
describe('Config object overload', () => {
|
|
11
|
+
it('TData should always be defined when initialData is provided as an object', () => {
|
|
12
|
+
const { data } = reactive(
|
|
13
|
+
useQuery({
|
|
14
|
+
queryKey: ['key'],
|
|
15
|
+
queryFn: () => {
|
|
16
|
+
return {
|
|
17
|
+
wow: true,
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
initialData: {
|
|
21
|
+
wow: true,
|
|
22
|
+
},
|
|
23
|
+
}),
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('TData should be defined when passed through queryOptions', () => {
|
|
30
|
+
const options = queryOptions({
|
|
31
|
+
queryKey: ['key'],
|
|
32
|
+
queryFn: () => {
|
|
33
|
+
return {
|
|
34
|
+
wow: true,
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
initialData: {
|
|
38
|
+
wow: true,
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
const { data } = reactive(useQuery(options))
|
|
42
|
+
|
|
43
|
+
expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('it should be possible to define a different TData than TQueryFnData using select with queryOptions spread into useQuery', () => {
|
|
47
|
+
const options = queryOptions({
|
|
48
|
+
queryKey: ['key'],
|
|
49
|
+
queryFn: () => Promise.resolve(1),
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const query = reactive(
|
|
53
|
+
useQuery({
|
|
54
|
+
...options,
|
|
55
|
+
select: (data) => data > 1,
|
|
56
|
+
}),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
expectTypeOf(query.data).toEqualTypeOf<boolean | undefined>()
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => {
|
|
63
|
+
const { data } = reactive(
|
|
64
|
+
useQuery({
|
|
65
|
+
queryKey: ['key'],
|
|
66
|
+
queryFn: () => {
|
|
67
|
+
return {
|
|
68
|
+
wow: true,
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
initialData: () => ({
|
|
72
|
+
wow: true,
|
|
73
|
+
}),
|
|
74
|
+
}),
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('TData should have undefined in the union when initialData is NOT provided', () => {
|
|
81
|
+
const { data } = reactive(
|
|
82
|
+
useQuery({
|
|
83
|
+
queryKey: ['key'],
|
|
84
|
+
queryFn: () => {
|
|
85
|
+
return {
|
|
86
|
+
wow: true,
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
}),
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {
|
|
96
|
+
const { data } = reactive(
|
|
97
|
+
useQuery({
|
|
98
|
+
queryKey: ['key'],
|
|
99
|
+
queryFn: () => {
|
|
100
|
+
return {
|
|
101
|
+
wow: true,
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
initialData: () => undefined as { wow: boolean } | undefined,
|
|
105
|
+
}),
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
it('TData should be narrowed after an isSuccess check when initialData is provided as a function which can return undefined', () => {
|
|
112
|
+
const { data, isSuccess } = reactive(
|
|
113
|
+
useQuery({
|
|
114
|
+
queryKey: ['key'],
|
|
115
|
+
queryFn: () => {
|
|
116
|
+
return {
|
|
117
|
+
wow: true,
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
initialData: () => undefined as { wow: boolean } | undefined,
|
|
121
|
+
}),
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
if (isSuccess) {
|
|
125
|
+
expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()
|
|
126
|
+
}
|
|
127
|
+
})
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
describe('custom composable', () => {
|
|
131
|
+
it('should allow custom composable using UseQueryOptions', () => {
|
|
132
|
+
const useCustomQuery = (
|
|
133
|
+
options?: OmitKeyof<
|
|
134
|
+
UseQueryOptions<string>,
|
|
135
|
+
'queryKey' | 'queryFn',
|
|
136
|
+
'safely'
|
|
137
|
+
>,
|
|
138
|
+
) => {
|
|
139
|
+
return useQuery({
|
|
140
|
+
...options,
|
|
141
|
+
queryKey: ['todos-key'],
|
|
142
|
+
queryFn: () => Promise.resolve('data'),
|
|
143
|
+
})
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const { data } = reactive(useCustomQuery())
|
|
147
|
+
|
|
148
|
+
expectTypeOf(data).toEqualTypeOf<string | undefined>()
|
|
149
|
+
})
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
describe('structuralSharing', () => {
|
|
153
|
+
it('should restrict to same types', () => {
|
|
154
|
+
useQuery({
|
|
155
|
+
queryKey: ['key'],
|
|
156
|
+
queryFn: () => 5,
|
|
157
|
+
structuralSharing: (_oldData, newData) => {
|
|
158
|
+
return newData
|
|
159
|
+
},
|
|
160
|
+
})
|
|
161
|
+
})
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
describe('Discriminated union return type', () => {
|
|
165
|
+
it('data should be possibly undefined by default', () => {
|
|
166
|
+
const query = reactive(
|
|
167
|
+
useQuery({
|
|
168
|
+
queryKey: ['key'],
|
|
169
|
+
queryFn: simpleFetcher,
|
|
170
|
+
}),
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
expectTypeOf(query.data).toEqualTypeOf<string | undefined>()
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
it('data should be defined when query is success', () => {
|
|
177
|
+
const query = reactive(
|
|
178
|
+
useQuery({
|
|
179
|
+
queryKey: ['key'],
|
|
180
|
+
queryFn: simpleFetcher,
|
|
181
|
+
}),
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
if (query.isSuccess) {
|
|
185
|
+
expectTypeOf(query.data).toEqualTypeOf<string>()
|
|
186
|
+
}
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
it('error should be null when query is success', () => {
|
|
190
|
+
const query = reactive(
|
|
191
|
+
useQuery({
|
|
192
|
+
queryKey: ['key'],
|
|
193
|
+
queryFn: simpleFetcher,
|
|
194
|
+
}),
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
if (query.isSuccess) {
|
|
198
|
+
expectTypeOf(query.error).toEqualTypeOf<null>()
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
it('data should be undefined when query is pending', () => {
|
|
203
|
+
const query = reactive(
|
|
204
|
+
useQuery({
|
|
205
|
+
queryKey: ['key'],
|
|
206
|
+
queryFn: simpleFetcher,
|
|
207
|
+
}),
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
if (query.isPending) {
|
|
211
|
+
expectTypeOf(query.data).toEqualTypeOf<undefined>()
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
it('error should be defined when query is error', () => {
|
|
216
|
+
const query = reactive(
|
|
217
|
+
useQuery({
|
|
218
|
+
queryKey: ['key'],
|
|
219
|
+
queryFn: simpleFetcher,
|
|
220
|
+
}),
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
if (query.isError) {
|
|
224
|
+
expectTypeOf(query.error).toEqualTypeOf<Error>()
|
|
225
|
+
}
|
|
226
|
+
})
|
|
227
|
+
})
|
|
228
|
+
})
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,11 @@ export { VueQueryPlugin } from './vueQueryPlugin'
|
|
|
6
6
|
export { QueryClient } from './queryClient'
|
|
7
7
|
export { QueryCache } from './queryCache'
|
|
8
8
|
export { queryOptions } from './queryOptions'
|
|
9
|
+
export { infiniteQueryOptions } from './infiniteQueryOptions'
|
|
10
|
+
export type {
|
|
11
|
+
DefinedInitialDataInfiniteOptions,
|
|
12
|
+
UndefinedInitialDataInfiniteOptions,
|
|
13
|
+
} from './infiniteQueryOptions'
|
|
9
14
|
export { MutationCache } from './mutationCache'
|
|
10
15
|
export { useQuery } from './useQuery'
|
|
11
16
|
export { useQueries } from './useQueries'
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { DataTag } from '@tanstack/query-core'
|
|
2
|
+
import type { InfiniteData } from '@tanstack/query-core'
|
|
3
|
+
import type { UseInfiniteQueryOptions } from './useInfiniteQuery'
|
|
4
|
+
import type { DefaultError, QueryKey } from '@tanstack/query-core'
|
|
5
|
+
|
|
6
|
+
export type UndefinedInitialDataInfiniteOptions<
|
|
7
|
+
TQueryFnData,
|
|
8
|
+
TError = DefaultError,
|
|
9
|
+
TData = InfiniteData<TQueryFnData>,
|
|
10
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
11
|
+
TPageParam = unknown,
|
|
12
|
+
> = UseInfiniteQueryOptions<
|
|
13
|
+
TQueryFnData,
|
|
14
|
+
TError,
|
|
15
|
+
TData,
|
|
16
|
+
TQueryFnData,
|
|
17
|
+
TQueryKey,
|
|
18
|
+
TPageParam
|
|
19
|
+
> & {
|
|
20
|
+
initialData?: undefined
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type NonUndefinedGuard<T> = T extends undefined ? never : T
|
|
24
|
+
|
|
25
|
+
export type DefinedInitialDataInfiniteOptions<
|
|
26
|
+
TQueryFnData,
|
|
27
|
+
TError = DefaultError,
|
|
28
|
+
TData = InfiniteData<TQueryFnData>,
|
|
29
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
30
|
+
TPageParam = unknown,
|
|
31
|
+
> = UseInfiniteQueryOptions<
|
|
32
|
+
TQueryFnData,
|
|
33
|
+
TError,
|
|
34
|
+
TData,
|
|
35
|
+
TQueryFnData,
|
|
36
|
+
TQueryKey,
|
|
37
|
+
TPageParam
|
|
38
|
+
> & {
|
|
39
|
+
initialData:
|
|
40
|
+
| NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>
|
|
41
|
+
| (() => NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function infiniteQueryOptions<
|
|
45
|
+
TQueryFnData,
|
|
46
|
+
TError = DefaultError,
|
|
47
|
+
TData = InfiniteData<TQueryFnData>,
|
|
48
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
49
|
+
TPageParam = unknown,
|
|
50
|
+
>(
|
|
51
|
+
options: UndefinedInitialDataInfiniteOptions<
|
|
52
|
+
TQueryFnData,
|
|
53
|
+
TError,
|
|
54
|
+
TData,
|
|
55
|
+
TQueryKey,
|
|
56
|
+
TPageParam
|
|
57
|
+
>,
|
|
58
|
+
): UndefinedInitialDataInfiniteOptions<
|
|
59
|
+
TQueryFnData,
|
|
60
|
+
TError,
|
|
61
|
+
TData,
|
|
62
|
+
TQueryKey,
|
|
63
|
+
TPageParam
|
|
64
|
+
> & {
|
|
65
|
+
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>>
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function infiniteQueryOptions<
|
|
69
|
+
TQueryFnData,
|
|
70
|
+
TError = DefaultError,
|
|
71
|
+
TData = InfiniteData<TQueryFnData>,
|
|
72
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
73
|
+
TPageParam = unknown,
|
|
74
|
+
>(
|
|
75
|
+
options: DefinedInitialDataInfiniteOptions<
|
|
76
|
+
TQueryFnData,
|
|
77
|
+
TError,
|
|
78
|
+
TData,
|
|
79
|
+
TQueryKey,
|
|
80
|
+
TPageParam
|
|
81
|
+
>,
|
|
82
|
+
): DefinedInitialDataInfiniteOptions<
|
|
83
|
+
TQueryFnData,
|
|
84
|
+
TError,
|
|
85
|
+
TData,
|
|
86
|
+
TQueryKey,
|
|
87
|
+
TPageParam
|
|
88
|
+
> & {
|
|
89
|
+
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>>
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function infiniteQueryOptions(options: unknown) {
|
|
93
|
+
return options
|
|
94
|
+
}
|
package/src/useQueries.ts
CHANGED
|
@@ -42,6 +42,9 @@ type UseQueryOptionsForUseQueries<
|
|
|
42
42
|
// Avoid TS depth-limit error in case of large array literal
|
|
43
43
|
type MAXIMUM_DEPTH = 20
|
|
44
44
|
|
|
45
|
+
// Widen the type of the symbol to enable type inference even if skipToken is not immutable.
|
|
46
|
+
type SkipTokenForUseQueries = symbol
|
|
47
|
+
|
|
45
48
|
type GetOptions<T> =
|
|
46
49
|
// Part 1: if UseQueryOptions are already being sent through, then just return T
|
|
47
50
|
T extends UseQueryOptions
|
|
@@ -66,34 +69,20 @@ type GetOptions<T> =
|
|
|
66
69
|
? UseQueryOptionsForUseQueries<TQueryFnData>
|
|
67
70
|
: // Part 4: responsible for inferring and enforcing type if no explicit parameter was provided
|
|
68
71
|
T extends {
|
|
69
|
-
queryFn?:
|
|
70
|
-
infer TQueryFnData,
|
|
71
|
-
|
|
72
|
-
>
|
|
72
|
+
queryFn?:
|
|
73
|
+
| QueryFunction<infer TQueryFnData, infer TQueryKey>
|
|
74
|
+
| SkipTokenForUseQueries
|
|
73
75
|
select?: (data: any) => infer TData
|
|
74
76
|
throwOnError?: ThrowOnError<any, infer TError, any, any>
|
|
75
77
|
}
|
|
76
78
|
? UseQueryOptionsForUseQueries<
|
|
77
79
|
TQueryFnData,
|
|
78
|
-
TError,
|
|
79
|
-
TData,
|
|
80
|
+
unknown extends TError ? DefaultError : TError,
|
|
81
|
+
unknown extends TData ? TQueryFnData : TData,
|
|
80
82
|
TQueryKey
|
|
81
83
|
>
|
|
82
|
-
:
|
|
83
|
-
|
|
84
|
-
infer TQueryFnData,
|
|
85
|
-
infer TQueryKey
|
|
86
|
-
>
|
|
87
|
-
throwOnError?: ThrowOnError<any, infer TError, any, any>
|
|
88
|
-
}
|
|
89
|
-
? UseQueryOptionsForUseQueries<
|
|
90
|
-
TQueryFnData,
|
|
91
|
-
TError,
|
|
92
|
-
TQueryFnData,
|
|
93
|
-
TQueryKey
|
|
94
|
-
>
|
|
95
|
-
: // Fallback
|
|
96
|
-
UseQueryOptionsForUseQueries
|
|
84
|
+
: // Fallback
|
|
85
|
+
UseQueryOptionsForUseQueries
|
|
97
86
|
|
|
98
87
|
// A defined initialData setting should return a DefinedQueryObserverResult rather than QueryObserverResult
|
|
99
88
|
type GetDefinedOrUndefinedQueryResult<T, TData, TError = unknown> = T extends {
|
|
@@ -124,7 +113,7 @@ type GetResults<T> =
|
|
|
124
113
|
? GetDefinedOrUndefinedQueryResult<
|
|
125
114
|
T,
|
|
126
115
|
undefined extends TData ? TQueryFnData : TData,
|
|
127
|
-
TError
|
|
116
|
+
unknown extends TError ? DefaultError : TError
|
|
128
117
|
>
|
|
129
118
|
: // Part 2: responsible for mapping explicit type parameter to function result, if object
|
|
130
119
|
T extends { queryFnData: any; error?: infer TError; data: infer TData }
|
|
@@ -142,7 +131,9 @@ type GetResults<T> =
|
|
|
142
131
|
? GetDefinedOrUndefinedQueryResult<T, TQueryFnData>
|
|
143
132
|
: // Part 4: responsible for mapping inferred type to results, if no explicit parameter was provided
|
|
144
133
|
T extends {
|
|
145
|
-
queryFn?:
|
|
134
|
+
queryFn?:
|
|
135
|
+
| QueryFunction<infer TQueryFnData, any>
|
|
136
|
+
| SkipTokenForUseQueries
|
|
146
137
|
select?: (data: any) => infer TData
|
|
147
138
|
throwOnError?: ThrowOnError<any, infer TError, any, any>
|
|
148
139
|
}
|
|
@@ -151,17 +142,8 @@ type GetResults<T> =
|
|
|
151
142
|
unknown extends TData ? TQueryFnData : TData,
|
|
152
143
|
unknown extends TError ? DefaultError : TError
|
|
153
144
|
>
|
|
154
|
-
:
|
|
155
|
-
|
|
156
|
-
throwOnError?: ThrowOnError<any, infer TError, any, any>
|
|
157
|
-
}
|
|
158
|
-
? GetDefinedOrUndefinedQueryResult<
|
|
159
|
-
T,
|
|
160
|
-
TQueryFnData,
|
|
161
|
-
unknown extends TError ? DefaultError : TError
|
|
162
|
-
>
|
|
163
|
-
: // Fallback
|
|
164
|
-
QueryObserverResult
|
|
145
|
+
: // Fallback
|
|
146
|
+
QueryObserverResult
|
|
165
147
|
|
|
166
148
|
/**
|
|
167
149
|
* UseQueriesOptions reducer recursively unwraps function arguments to infer/enforce type param
|
|
@@ -182,7 +164,7 @@ export type UseQueriesOptions<
|
|
|
182
164
|
[...TResult, GetOptions<Head>],
|
|
183
165
|
[...TDepth, 1]
|
|
184
166
|
>
|
|
185
|
-
:
|
|
167
|
+
: ReadonlyArray<unknown> extends T
|
|
186
168
|
? T
|
|
187
169
|
: // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!
|
|
188
170
|
// use this to infer the param types in the case of Array.map() argument
|
|
@@ -236,7 +218,7 @@ export type UseQueriesResults<
|
|
|
236
218
|
Array<
|
|
237
219
|
QueryObserverResult<
|
|
238
220
|
unknown extends TData ? TQueryFnData : TData,
|
|
239
|
-
TError
|
|
221
|
+
unknown extends TError ? DefaultError : TError
|
|
240
222
|
>
|
|
241
223
|
>
|
|
242
224
|
: // Fallback
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'vitest'
|
|
2
|
-
import { QueryClient } from '../queryClient'
|
|
3
|
-
import { doNotExecute } from './test-utils'
|
|
4
|
-
import type { Equal, Expect } from './test-utils'
|
|
5
|
-
import type { DataTag, InfiniteData } from '@tanstack/query-core'
|
|
6
|
-
|
|
7
|
-
describe('getQueryData', () => {
|
|
8
|
-
it('should be typed if key is tagged', () => {
|
|
9
|
-
doNotExecute(() => {
|
|
10
|
-
const queryKey = ['key'] as DataTag<Array<string>, number>
|
|
11
|
-
const queryClient = new QueryClient()
|
|
12
|
-
const data = queryClient.getQueryData(queryKey)
|
|
13
|
-
|
|
14
|
-
const result: Expect<Equal<typeof data, number | undefined>> = true
|
|
15
|
-
return result
|
|
16
|
-
})
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
it('should infer unknown if key is not tagged', () => {
|
|
20
|
-
doNotExecute(() => {
|
|
21
|
-
const queryKey = ['key'] as const
|
|
22
|
-
const queryClient = new QueryClient()
|
|
23
|
-
const data = queryClient.getQueryData(queryKey)
|
|
24
|
-
|
|
25
|
-
const result: Expect<Equal<typeof data, unknown>> = true
|
|
26
|
-
return result
|
|
27
|
-
})
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('should infer passed generic if passed', () => {
|
|
31
|
-
doNotExecute(() => {
|
|
32
|
-
const queryKey = ['key'] as const
|
|
33
|
-
const queryClient = new QueryClient()
|
|
34
|
-
const data = queryClient.getQueryData<number>(queryKey)
|
|
35
|
-
|
|
36
|
-
const result: Expect<Equal<typeof data, number | undefined>> = true
|
|
37
|
-
return result
|
|
38
|
-
})
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
it('should only allow Arrays to be passed', () => {
|
|
42
|
-
doNotExecute(() => {
|
|
43
|
-
const queryKey = 'key' as const
|
|
44
|
-
const queryClient = new QueryClient()
|
|
45
|
-
// @ts-expect-error TS2345: Argument of type 'string' is not assignable to parameter of type 'QueryKey'
|
|
46
|
-
return queryClient.getQueryData(queryKey)
|
|
47
|
-
})
|
|
48
|
-
})
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
describe('setQueryData', () => {
|
|
52
|
-
it('updater should be typed if key is tagged', () => {
|
|
53
|
-
doNotExecute(() => {
|
|
54
|
-
const queryKey = ['key'] as DataTag<Array<string>, number>
|
|
55
|
-
const queryClient = new QueryClient()
|
|
56
|
-
const data = queryClient.setQueryData(queryKey, (prev) => {
|
|
57
|
-
const result: Expect<Equal<typeof prev, number | undefined>> = true
|
|
58
|
-
return result ? prev : 1
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
const result: Expect<Equal<typeof data, number | undefined>> = true
|
|
62
|
-
return result
|
|
63
|
-
})
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
it('value should be typed if key is tagged', () => {
|
|
67
|
-
doNotExecute(() => {
|
|
68
|
-
const queryKey = ['key'] as DataTag<Array<string>, number>
|
|
69
|
-
const queryClient = new QueryClient()
|
|
70
|
-
|
|
71
|
-
// @ts-expect-error value should be a number
|
|
72
|
-
queryClient.setQueryData(queryKey, '1')
|
|
73
|
-
|
|
74
|
-
// @ts-expect-error value should be a number
|
|
75
|
-
queryClient.setQueryData(queryKey, () => '1')
|
|
76
|
-
|
|
77
|
-
const data = queryClient.setQueryData(queryKey, 1)
|
|
78
|
-
|
|
79
|
-
const result: Expect<Equal<typeof data, number | undefined>> = true
|
|
80
|
-
return result
|
|
81
|
-
})
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('should infer unknown for updater if key is not tagged', () => {
|
|
85
|
-
doNotExecute(() => {
|
|
86
|
-
const queryKey = ['key'] as const
|
|
87
|
-
const queryClient = new QueryClient()
|
|
88
|
-
const data = queryClient.setQueryData(queryKey, (prev) => {
|
|
89
|
-
const result: Expect<Equal<typeof prev, unknown>> = true
|
|
90
|
-
return result ? prev : 1
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
const result: Expect<Equal<typeof data, unknown>> = true
|
|
94
|
-
return result
|
|
95
|
-
})
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
it('should infer unknown for value if key is not tagged', () => {
|
|
99
|
-
doNotExecute(() => {
|
|
100
|
-
const queryKey = ['key'] as const
|
|
101
|
-
const queryClient = new QueryClient()
|
|
102
|
-
const data = queryClient.setQueryData(queryKey, 'foo')
|
|
103
|
-
|
|
104
|
-
const result: Expect<Equal<typeof data, unknown>> = true
|
|
105
|
-
return result
|
|
106
|
-
})
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
it('should infer passed generic if passed', () => {
|
|
110
|
-
doNotExecute(() => {
|
|
111
|
-
const queryKey = ['key'] as const
|
|
112
|
-
const queryClient = new QueryClient()
|
|
113
|
-
const data = queryClient.setQueryData<string>(queryKey, (prev) => {
|
|
114
|
-
const result: Expect<Equal<typeof prev, string | undefined>> = true
|
|
115
|
-
return result ? prev : '1'
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
const result: Expect<Equal<typeof data, string | undefined>> = true
|
|
119
|
-
return result
|
|
120
|
-
})
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
it('should infer passed generic for value', () => {
|
|
124
|
-
doNotExecute(() => {
|
|
125
|
-
const queryKey = ['key'] as const
|
|
126
|
-
const queryClient = new QueryClient()
|
|
127
|
-
const data = queryClient.setQueryData<string>(queryKey, 'foo')
|
|
128
|
-
|
|
129
|
-
const result: Expect<Equal<typeof data, string | undefined>> = true
|
|
130
|
-
return result
|
|
131
|
-
})
|
|
132
|
-
})
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
describe('fetchInfiniteQuery', () => {
|
|
136
|
-
it('should allow passing pages', () => {
|
|
137
|
-
doNotExecute(async () => {
|
|
138
|
-
const data = await new QueryClient().fetchInfiniteQuery({
|
|
139
|
-
queryKey: ['key'],
|
|
140
|
-
queryFn: () => Promise.resolve('string'),
|
|
141
|
-
getNextPageParam: () => 1,
|
|
142
|
-
initialPageParam: 1,
|
|
143
|
-
pages: 5,
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
const result: Expect<Equal<typeof data, InfiniteData<string, number>>> =
|
|
147
|
-
true
|
|
148
|
-
return result
|
|
149
|
-
})
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
it('should not allow passing getNextPageParam without pages', () => {
|
|
153
|
-
doNotExecute(async () => {
|
|
154
|
-
return new QueryClient().fetchInfiniteQuery({
|
|
155
|
-
queryKey: ['key'],
|
|
156
|
-
queryFn: () => Promise.resolve('string'),
|
|
157
|
-
initialPageParam: 1,
|
|
158
|
-
getNextPageParam: () => 1,
|
|
159
|
-
})
|
|
160
|
-
})
|
|
161
|
-
})
|
|
162
|
-
|
|
163
|
-
it('should not allow passing pages without getNextPageParam', () => {
|
|
164
|
-
doNotExecute(async () => {
|
|
165
|
-
// @ts-expect-error Property 'getNextPageParam' is missing
|
|
166
|
-
return new QueryClient().fetchInfiniteQuery({
|
|
167
|
-
queryKey: ['key'],
|
|
168
|
-
queryFn: () => Promise.resolve('string'),
|
|
169
|
-
initialPageParam: 1,
|
|
170
|
-
pages: 5,
|
|
171
|
-
})
|
|
172
|
-
})
|
|
173
|
-
})
|
|
174
|
-
})
|