@tanstack/query-core 5.25.0 → 5.27.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.
Files changed (42) hide show
  1. package/build/legacy/focusManager.cjs +2 -1
  2. package/build/legacy/focusManager.cjs.map +1 -1
  3. package/build/legacy/focusManager.d.cts +2 -1
  4. package/build/legacy/focusManager.d.ts +2 -1
  5. package/build/legacy/focusManager.js +2 -1
  6. package/build/legacy/focusManager.js.map +1 -1
  7. package/build/legacy/queryClient.cjs +2 -2
  8. package/build/legacy/queryClient.cjs.map +1 -1
  9. package/build/legacy/queryClient.js +2 -2
  10. package/build/legacy/queryClient.js.map +1 -1
  11. package/build/legacy/utils.cjs +1 -1
  12. package/build/legacy/utils.cjs.map +1 -1
  13. package/build/legacy/utils.js +1 -1
  14. package/build/legacy/utils.js.map +1 -1
  15. package/build/modern/focusManager.cjs +2 -1
  16. package/build/modern/focusManager.cjs.map +1 -1
  17. package/build/modern/focusManager.d.cts +2 -1
  18. package/build/modern/focusManager.d.ts +2 -1
  19. package/build/modern/focusManager.js +2 -1
  20. package/build/modern/focusManager.js.map +1 -1
  21. package/build/modern/queryClient.cjs +2 -2
  22. package/build/modern/queryClient.cjs.map +1 -1
  23. package/build/modern/queryClient.js +2 -2
  24. package/build/modern/queryClient.js.map +1 -1
  25. package/build/modern/utils.cjs +1 -1
  26. package/build/modern/utils.cjs.map +1 -1
  27. package/build/modern/utils.js +1 -1
  28. package/build/modern/utils.js.map +1 -1
  29. package/package.json +1 -1
  30. package/src/focusManager.ts +5 -2
  31. package/src/queryClient.ts +2 -2
  32. package/src/tests/focusManager.test.tsx +3 -0
  33. package/src/tests/infiniteQueryObserver.test-d.tsx +62 -0
  34. package/src/tests/infiniteQueryObserver.test.tsx +2 -51
  35. package/src/tests/query.test.tsx +9 -3
  36. package/src/tests/queryClient.test-d.tsx +135 -0
  37. package/src/tests/queryObserver.test-d.tsx +108 -0
  38. package/src/tests/queryObserver.test.tsx +6 -40
  39. package/src/tests/utils.ts +0 -10
  40. package/src/utils.ts +1 -1
  41. package/src/tests/queryClient.types.test.tsx +0 -174
  42. package/src/tests/queryObserver.types.test.tsx +0 -66
@@ -0,0 +1,135 @@
1
+ import { describe, expectTypeOf, it } from 'vitest'
2
+ import { QueryClient } from '../queryClient'
3
+ import type { DataTag, InfiniteData } from '../types'
4
+
5
+ describe('getQueryData', () => {
6
+ it('should be typed if key is tagged', () => {
7
+ const queryKey = ['key'] as DataTag<Array<string>, number>
8
+ const queryClient = new QueryClient()
9
+ const data = queryClient.getQueryData(queryKey)
10
+
11
+ expectTypeOf(data).toEqualTypeOf<number | undefined>()
12
+ })
13
+
14
+ it('should infer unknown if key is not tagged', () => {
15
+ const queryKey = ['key'] as const
16
+ const queryClient = new QueryClient()
17
+ const data = queryClient.getQueryData(queryKey)
18
+
19
+ expectTypeOf(data).toEqualTypeOf<unknown>()
20
+ })
21
+
22
+ it('should infer passed generic if passed', () => {
23
+ const queryKey = ['key'] as const
24
+ const queryClient = new QueryClient()
25
+ const data = queryClient.getQueryData<number>(queryKey)
26
+
27
+ expectTypeOf(data).toEqualTypeOf<number | undefined>()
28
+ })
29
+
30
+ it('should only allow Arrays to be passed', () => {
31
+ const queryKey = 'key' as const
32
+ const queryClient = new QueryClient()
33
+ // @ts-expect-error TS2345: Argument of type 'string' is not assignable to parameter of type 'QueryKey'
34
+ return queryClient.getQueryData(queryKey)
35
+ })
36
+ })
37
+
38
+ describe('setQueryData', () => {
39
+ it('updater should be typed if key is tagged', () => {
40
+ const queryKey = ['key'] as DataTag<Array<string>, number>
41
+ const queryClient = new QueryClient()
42
+ const data = queryClient.setQueryData(queryKey, (prev) => {
43
+ expectTypeOf(prev).toEqualTypeOf<number | undefined>()
44
+ return prev
45
+ })
46
+
47
+ expectTypeOf(data).toEqualTypeOf<number | undefined>()
48
+ })
49
+
50
+ it('value should be typed if key is tagged', () => {
51
+ const queryKey = ['key'] as DataTag<Array<string>, number>
52
+ const queryClient = new QueryClient()
53
+
54
+ // @ts-expect-error value should be a number
55
+ queryClient.setQueryData(queryKey, '1')
56
+
57
+ // @ts-expect-error value should be a number
58
+ queryClient.setQueryData(queryKey, () => '1')
59
+
60
+ const data = queryClient.setQueryData(queryKey, 1)
61
+
62
+ expectTypeOf(data).toEqualTypeOf<number | undefined>()
63
+ })
64
+
65
+ it('should infer unknown for updater if key is not tagged', () => {
66
+ const queryKey = ['key'] as const
67
+ const queryClient = new QueryClient()
68
+ const data = queryClient.setQueryData(queryKey, (prev) => {
69
+ expectTypeOf(prev).toEqualTypeOf<unknown>()
70
+ return prev
71
+ })
72
+
73
+ expectTypeOf(data).toEqualTypeOf<unknown>()
74
+ })
75
+
76
+ it('should infer unknown for value if key is not tagged', () => {
77
+ const queryKey = ['key'] as const
78
+ const queryClient = new QueryClient()
79
+ const data = queryClient.setQueryData(queryKey, 'foo')
80
+
81
+ expectTypeOf(data).toEqualTypeOf<unknown>()
82
+ })
83
+
84
+ it('should infer passed generic if passed', () => {
85
+ const queryKey = ['key'] as const
86
+ const queryClient = new QueryClient()
87
+ const data = queryClient.setQueryData<string>(queryKey, (prev) => {
88
+ expectTypeOf(prev).toEqualTypeOf<string | undefined>()
89
+ return prev
90
+ })
91
+
92
+ expectTypeOf(data).toEqualTypeOf<string | undefined>()
93
+ })
94
+
95
+ it('should infer passed generic for value', () => {
96
+ const queryKey = ['key'] as const
97
+ const queryClient = new QueryClient()
98
+ const data = queryClient.setQueryData<string>(queryKey, 'foo')
99
+
100
+ expectTypeOf(data).toEqualTypeOf<string | undefined>()
101
+ })
102
+ })
103
+
104
+ describe('fetchInfiniteQuery', () => {
105
+ it('should allow passing pages', async () => {
106
+ const data = await new QueryClient().fetchInfiniteQuery({
107
+ queryKey: ['key'],
108
+ queryFn: () => Promise.resolve('string'),
109
+ getNextPageParam: () => 1,
110
+ initialPageParam: 1,
111
+ pages: 5,
112
+ })
113
+
114
+ expectTypeOf(data).toEqualTypeOf<InfiniteData<string, number>>()
115
+ })
116
+
117
+ it('should not allow passing getNextPageParam without pages', () => {
118
+ new QueryClient().fetchInfiniteQuery({
119
+ queryKey: ['key'],
120
+ queryFn: () => Promise.resolve('string'),
121
+ initialPageParam: 1,
122
+ getNextPageParam: () => 1,
123
+ })
124
+ })
125
+
126
+ it('should not allow passing pages without getNextPageParam', () => {
127
+ // @ts-expect-error Property 'getNextPageParam' is missing
128
+ return new QueryClient().fetchInfiniteQuery({
129
+ queryKey: ['key'],
130
+ queryFn: () => Promise.resolve('string'),
131
+ initialPageParam: 1,
132
+ pages: 5,
133
+ })
134
+ })
135
+ })
@@ -0,0 +1,108 @@
1
+ import { afterEach, beforeEach, describe, expectTypeOf, it } from 'vitest'
2
+ import { QueryObserver } from '..'
3
+ import { createQueryClient, queryKey } from './utils'
4
+ import type { QueryClient } from '..'
5
+
6
+ describe('queryObserver', () => {
7
+ let queryClient: QueryClient
8
+
9
+ beforeEach(() => {
10
+ queryClient = createQueryClient()
11
+ queryClient.mount()
12
+ })
13
+
14
+ afterEach(() => {
15
+ queryClient.clear()
16
+ })
17
+
18
+ it('should be inferred as a correct result type', () => {
19
+ const observer = new QueryObserver(queryClient, {
20
+ queryKey: queryKey(),
21
+ queryFn: () => Promise.resolve({ value: 'data' }),
22
+ })
23
+
24
+ const result = observer.getCurrentResult()
25
+
26
+ if (result.isPending) {
27
+ expectTypeOf(result.data).toEqualTypeOf<undefined>()
28
+ expectTypeOf(result.error).toEqualTypeOf<null>()
29
+ expectTypeOf(result.isLoading).toEqualTypeOf<boolean>()
30
+ expectTypeOf(result.status).toEqualTypeOf<'pending'>()
31
+ }
32
+ if (result.isLoading) {
33
+ expectTypeOf(result.data).toEqualTypeOf<undefined>()
34
+ expectTypeOf(result.error).toEqualTypeOf<null>()
35
+ expectTypeOf(result.isPending).toEqualTypeOf<true>()
36
+ expectTypeOf(result.status).toEqualTypeOf<'pending'>()
37
+ }
38
+
39
+ if (result.isLoadingError) {
40
+ expectTypeOf(result.data).toEqualTypeOf<undefined>()
41
+ expectTypeOf(result.error).toEqualTypeOf<Error>()
42
+ expectTypeOf(result.status).toEqualTypeOf<'error'>()
43
+ }
44
+
45
+ if (result.isRefetchError) {
46
+ expectTypeOf(result.data).toEqualTypeOf<{ value: string }>()
47
+ expectTypeOf(result.error).toEqualTypeOf<Error>()
48
+ expectTypeOf(result.status).toEqualTypeOf<'error'>()
49
+ }
50
+
51
+ if (result.isSuccess) {
52
+ expectTypeOf(result.data).toEqualTypeOf<{ value: string }>()
53
+ expectTypeOf(result.error).toEqualTypeOf<null>()
54
+ expectTypeOf(result.status).toEqualTypeOf<'success'>()
55
+ }
56
+ })
57
+
58
+ describe('placeholderData', () => {
59
+ it('previousQuery should have typed queryKey', () => {
60
+ const testQueryKey = ['SomeQuery', 42, { foo: 'bar' }] as const
61
+
62
+ new QueryObserver(createQueryClient(), {
63
+ queryKey: testQueryKey,
64
+ placeholderData: (_, previousQuery) => {
65
+ if (previousQuery) {
66
+ expectTypeOf(previousQuery.queryKey).toEqualTypeOf<
67
+ typeof testQueryKey
68
+ >()
69
+ }
70
+ },
71
+ })
72
+ })
73
+
74
+ it('previousQuery should have typed error', () => {
75
+ class CustomError extends Error {
76
+ name = 'CustomError' as const
77
+ }
78
+
79
+ new QueryObserver<boolean, CustomError>(createQueryClient(), {
80
+ queryKey: ['key'],
81
+ placeholderData: (_, previousQuery) => {
82
+ if (previousQuery) {
83
+ expectTypeOf(
84
+ previousQuery.state.error,
85
+ ).toEqualTypeOf<CustomError | null>()
86
+ }
87
+ return undefined
88
+ },
89
+ })
90
+ })
91
+
92
+ it('previousData should have the same type as query data', () => {
93
+ const queryData = { foo: 'bar' } as const
94
+
95
+ new QueryObserver(createQueryClient(), {
96
+ queryKey: ['key'],
97
+ queryFn: () => queryData,
98
+ select: (data) => data.foo,
99
+ placeholderData: (previousData) => {
100
+ expectTypeOf(previousData).toEqualTypeOf<
101
+ typeof queryData | undefined
102
+ >()
103
+ return undefined
104
+ },
105
+ })
106
+ })
107
+ })
108
+ })
@@ -120,7 +120,9 @@ describe('queryObserver', () => {
120
120
  })
121
121
  let observerResult
122
122
  const unsubscribe = observer.subscribe((result) => {
123
- expectTypeOf<QueryObserverResult<{ myCount: number }>>(result)
123
+ expectTypeOf(result).toEqualTypeOf<
124
+ QueryObserverResult<{ myCount: number }>
125
+ >()
124
126
  observerResult = result
125
127
  })
126
128
  await sleep(1)
@@ -136,7 +138,9 @@ describe('queryObserver', () => {
136
138
  select: (data) => ({ myCount: data.count }),
137
139
  })
138
140
  const observerResult = await observer.refetch()
139
- expectTypeOf<{ myCount: number } | undefined>(observerResult.data)
141
+ expectTypeOf(observerResult.data).toEqualTypeOf<
142
+ { myCount: number } | undefined
143
+ >()
140
144
  expect(observerResult.data).toMatchObject({ myCount: 1 })
141
145
  })
142
146
 
@@ -894,42 +898,4 @@ describe('queryObserver', () => {
894
898
 
895
899
  unsubscribe()
896
900
  })
897
-
898
- test('should be inferred as a correct result type', async () => {
899
- const key = queryKey()
900
- const data = { value: 'data' }
901
- const observer = new QueryObserver(queryClient, {
902
- queryKey: key,
903
- queryFn: () => Promise.resolve(data),
904
- })
905
-
906
- const result = observer.getCurrentResult()
907
-
908
- result.isPending &&
909
- expectTypeOf<undefined>(result.data) &&
910
- expectTypeOf<null>(result.error) &&
911
- expectTypeOf<boolean>(result.isLoading) &&
912
- expectTypeOf<'pending'>(result.status)
913
-
914
- result.isLoading &&
915
- expectTypeOf<undefined>(result.data) &&
916
- expectTypeOf<null>(result.error) &&
917
- expectTypeOf<true>(result.isPending) &&
918
- expectTypeOf<'pending'>(result.status)
919
-
920
- result.isLoadingError &&
921
- expectTypeOf<undefined>(result.data) &&
922
- expectTypeOf<Error>(result.error) &&
923
- expectTypeOf<'error'>(result.status)
924
-
925
- result.isRefetchError &&
926
- expectTypeOf<{ value: string }>(result.data) &&
927
- expectTypeOf<Error>(result.error) &&
928
- expectTypeOf<'error'>(result.status)
929
-
930
- result.isSuccess &&
931
- expectTypeOf<{ value: string }>(result.data) &&
932
- expectTypeOf<null>(result.error) &&
933
- expectTypeOf<'success'>(result.status)
934
- })
935
901
  })
@@ -57,13 +57,3 @@ export function setIsServer(isServer: boolean) {
57
57
  })
58
58
  }
59
59
  }
60
-
61
- export const doNotExecute = (_func: () => void) => true
62
-
63
- export type Equal<TTargetA, TTargetB> = (<T>() => T extends TTargetA
64
- ? 1
65
- : 2) extends <T>() => T extends TTargetB ? 1 : 2
66
- ? true
67
- : false
68
-
69
- export type Expect<T extends true> = T
package/src/utils.ts CHANGED
@@ -62,7 +62,7 @@ export type QueryTypeFilter = 'all' | 'active' | 'inactive'
62
62
 
63
63
  // UTILS
64
64
 
65
- export const isServer = typeof window === 'undefined' || 'Deno' in window
65
+ export const isServer = typeof window === 'undefined' || 'Deno' in globalThis
66
66
 
67
67
  export function noop(): undefined {
68
68
  return undefined
@@ -1,174 +0,0 @@
1
- import { describe, it } from 'vitest'
2
- import { QueryClient } from '../queryClient'
3
- import { doNotExecute } from './utils'
4
- import type { Equal, Expect } from './utils'
5
- import type { DataTag, InfiniteData } from '../types'
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,66 +0,0 @@
1
- import { describe, it } from 'vitest'
2
- import { QueryObserver } from '..'
3
- import { createQueryClient, doNotExecute } from './utils'
4
- import type { Equal, Expect } from './utils'
5
-
6
- describe('placeholderData', () => {
7
- describe('placeholderData function', () => {
8
- it('previousQuery should have typed queryKey', () => {
9
- doNotExecute(() => {
10
- const queryKey = ['SomeQuery', 42, { foo: 'bar' }] as const
11
- type QueryKey = typeof queryKey
12
-
13
- new QueryObserver(createQueryClient(), {
14
- queryKey,
15
- placeholderData: (_, previousQuery) => {
16
- const previousQueryKey = previousQuery?.queryKey
17
-
18
- const result: Expect<
19
- Equal<typeof previousQueryKey, QueryKey | undefined>
20
- > = true
21
- return result
22
- },
23
- })
24
- })
25
- })
26
-
27
- it('previousQuery should have typed error', () => {
28
- doNotExecute(() => {
29
- class CustomError extends Error {
30
- name = 'CustomError' as const
31
- }
32
-
33
- new QueryObserver<boolean, CustomError>(createQueryClient(), {
34
- queryKey: ['key'],
35
- placeholderData: (_, previousQuery) => {
36
- const error = previousQuery?.state.error
37
-
38
- const result: Expect<
39
- Equal<typeof error, CustomError | null | undefined>
40
- > = true
41
- return result
42
- },
43
- })
44
- })
45
- })
46
-
47
- it('previousData should have the same type as query data', () => {
48
- doNotExecute(() => {
49
- const queryData = { foo: 'bar' } as const
50
- type QueryData = typeof queryData
51
-
52
- new QueryObserver(createQueryClient(), {
53
- queryKey: ['key'],
54
- queryFn: () => queryData,
55
- select: (data) => data.foo,
56
- placeholderData: (previousData) => {
57
- const result: Expect<
58
- Equal<typeof previousData, QueryData | undefined>
59
- > = true
60
- return result ? previousData : undefined
61
- },
62
- })
63
- })
64
- })
65
- })
66
- })