@tanstack/vue-query 5.40.0 → 5.40.1
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/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/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__/queryClient.test-d.ts +132 -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__/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/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/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
|
-
})
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'vitest'
|
|
2
|
-
import { reactive, ref } from 'vue-demi'
|
|
3
|
-
import { QueryClient } from '../queryClient'
|
|
4
|
-
import { queryOptions } from '../queryOptions'
|
|
5
|
-
import { useQuery } from '../useQuery'
|
|
6
|
-
import { doNotExecute } from './test-utils'
|
|
7
|
-
import type { dataTagSymbol } from '@tanstack/query-core'
|
|
8
|
-
import type { Equal, Expect } from './test-utils'
|
|
9
|
-
|
|
10
|
-
describe('queryOptions', () => {
|
|
11
|
-
it('should not allow excess properties', () => {
|
|
12
|
-
doNotExecute(() => {
|
|
13
|
-
return queryOptions({
|
|
14
|
-
queryKey: ['key'],
|
|
15
|
-
queryFn: () => Promise.resolve(5),
|
|
16
|
-
// @ts-expect-error this is a good error, because stallTime does not exist!
|
|
17
|
-
stallTime: 1000,
|
|
18
|
-
})
|
|
19
|
-
})
|
|
20
|
-
})
|
|
21
|
-
it('should infer types for callbacks', () => {
|
|
22
|
-
doNotExecute(() => {
|
|
23
|
-
return queryOptions({
|
|
24
|
-
queryKey: ['key'],
|
|
25
|
-
queryFn: () => Promise.resolve(5),
|
|
26
|
-
staleTime: 1000,
|
|
27
|
-
select: (data) => {
|
|
28
|
-
const result: Expect<Equal<number, typeof data>> = true
|
|
29
|
-
return result
|
|
30
|
-
},
|
|
31
|
-
})
|
|
32
|
-
})
|
|
33
|
-
})
|
|
34
|
-
it('should work when passed to useQuery', () => {
|
|
35
|
-
doNotExecute(() => {
|
|
36
|
-
const options = queryOptions({
|
|
37
|
-
queryKey: ['key'],
|
|
38
|
-
queryFn: () => Promise.resolve(5),
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
const { data } = reactive(useQuery(options))
|
|
42
|
-
|
|
43
|
-
const result: Expect<Equal<typeof data, number | undefined>> = true
|
|
44
|
-
|
|
45
|
-
return result
|
|
46
|
-
})
|
|
47
|
-
})
|
|
48
|
-
it('should tag the queryKey with the result type of the QueryFn', () => {
|
|
49
|
-
doNotExecute(() => {
|
|
50
|
-
const { queryKey } = queryOptions({
|
|
51
|
-
queryKey: ['key'],
|
|
52
|
-
queryFn: () => Promise.resolve(5),
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
const result: Expect<
|
|
56
|
-
Equal<(typeof queryKey)[typeof dataTagSymbol], number>
|
|
57
|
-
> = true
|
|
58
|
-
return result
|
|
59
|
-
})
|
|
60
|
-
})
|
|
61
|
-
it('should tag the queryKey even if no promise is returned', () => {
|
|
62
|
-
doNotExecute(() => {
|
|
63
|
-
const { queryKey } = queryOptions({
|
|
64
|
-
queryKey: ['key'],
|
|
65
|
-
queryFn: () => 5,
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
const result: Expect<
|
|
69
|
-
Equal<(typeof queryKey)[typeof dataTagSymbol], number>
|
|
70
|
-
> = true
|
|
71
|
-
return result
|
|
72
|
-
})
|
|
73
|
-
})
|
|
74
|
-
it('should tag the queryKey with unknown if there is no queryFn', () => {
|
|
75
|
-
doNotExecute(() => {
|
|
76
|
-
const { queryKey } = queryOptions({
|
|
77
|
-
queryKey: ['key'],
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
const result: Expect<
|
|
81
|
-
Equal<(typeof queryKey)[typeof dataTagSymbol], unknown>
|
|
82
|
-
> = true
|
|
83
|
-
return result
|
|
84
|
-
})
|
|
85
|
-
})
|
|
86
|
-
it('should tag the queryKey with the result type of the QueryFn if select is used', () => {
|
|
87
|
-
doNotExecute(() => {
|
|
88
|
-
const { queryKey } = queryOptions({
|
|
89
|
-
queryKey: ['key'],
|
|
90
|
-
queryFn: () => Promise.resolve(5),
|
|
91
|
-
select: (data) => data.toString(),
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
const result: Expect<
|
|
95
|
-
Equal<(typeof queryKey)[typeof dataTagSymbol], number>
|
|
96
|
-
> = true
|
|
97
|
-
return result
|
|
98
|
-
})
|
|
99
|
-
})
|
|
100
|
-
it('should return the proper type when passed to getQueryData', () => {
|
|
101
|
-
doNotExecute(() => {
|
|
102
|
-
const { queryKey } = queryOptions({
|
|
103
|
-
queryKey: ['key'],
|
|
104
|
-
queryFn: () => Promise.resolve(5),
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
const queryClient = new QueryClient()
|
|
108
|
-
const data = queryClient.getQueryData(queryKey)
|
|
109
|
-
|
|
110
|
-
const result: Expect<Equal<typeof data, number | undefined>> = true
|
|
111
|
-
return result
|
|
112
|
-
})
|
|
113
|
-
})
|
|
114
|
-
it('should properly type updaterFn when passed to setQueryData', () => {
|
|
115
|
-
doNotExecute(() => {
|
|
116
|
-
const { queryKey } = queryOptions({
|
|
117
|
-
queryKey: ['key'],
|
|
118
|
-
queryFn: () => Promise.resolve(5),
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
const queryClient = new QueryClient()
|
|
122
|
-
const data = queryClient.setQueryData(queryKey, (prev) => {
|
|
123
|
-
const result: Expect<Equal<typeof prev, number | undefined>> = true
|
|
124
|
-
return result ? prev : 1
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
const result: Expect<Equal<typeof data, number | undefined>> = true
|
|
128
|
-
return result
|
|
129
|
-
})
|
|
130
|
-
})
|
|
131
|
-
it('should properly type value when passed to setQueryData', () => {
|
|
132
|
-
doNotExecute(() => {
|
|
133
|
-
const { queryKey } = queryOptions({
|
|
134
|
-
queryKey: ['key'],
|
|
135
|
-
queryFn: () => Promise.resolve(5),
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
const queryClient = new QueryClient()
|
|
139
|
-
|
|
140
|
-
// @ts-expect-error value should be a number
|
|
141
|
-
queryClient.setQueryData(queryKey, '5')
|
|
142
|
-
// @ts-expect-error value should be a number
|
|
143
|
-
queryClient.setQueryData(queryKey, () => '5')
|
|
144
|
-
|
|
145
|
-
const data = queryClient.setQueryData(queryKey, 5)
|
|
146
|
-
|
|
147
|
-
const result: Expect<Equal<typeof data, number | undefined>> = true
|
|
148
|
-
return result
|
|
149
|
-
})
|
|
150
|
-
})
|
|
151
|
-
it('should allow to be passed to QueryClient methods while containing ref in queryKey', () => {
|
|
152
|
-
doNotExecute(() => {
|
|
153
|
-
const options = queryOptions({
|
|
154
|
-
queryKey: ['key', ref(1), { nested: ref(2) }],
|
|
155
|
-
queryFn: () => Promise.resolve(5),
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
const queryClient = new QueryClient()
|
|
159
|
-
|
|
160
|
-
// Should not error
|
|
161
|
-
const data = queryClient.invalidateQueries(options)
|
|
162
|
-
// Should not error
|
|
163
|
-
const data2 = queryClient.fetchQuery(options)
|
|
164
|
-
|
|
165
|
-
const result: Expect<Equal<typeof data, Promise<void>>> = true
|
|
166
|
-
const result2: Expect<Equal<typeof data2, Promise<number>>> = true
|
|
167
|
-
return result || result2
|
|
168
|
-
})
|
|
169
|
-
})
|
|
170
|
-
})
|