Skip to content

Commit a535a46

Browse files
fix(vue-query): reorder queryOptions and useQuery function overloads to fix type inference (#9088)
* fix(vue-query): more specific function overloads for queryOptions and useQuery to come before general ones (#9069) This instructs TypeScript to pick correct function overload when initialData is defined. * ci: apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent df8e02b commit a535a46

File tree

4 files changed

+112
-9
lines changed

4 files changed

+112
-9
lines changed

packages/vue-query/src/__tests__/queryOptions.test-d.ts

+88
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,92 @@ describe('queryOptions', () => {
122122
expectTypeOf(data).toEqualTypeOf<Promise<void>>()
123123
expectTypeOf(data2).toEqualTypeOf<Promise<number>>()
124124
})
125+
126+
it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => {
127+
const { data } = reactive(
128+
useQuery(
129+
queryOptions({
130+
queryKey: ['key'],
131+
queryFn: () => {
132+
return {
133+
wow: true,
134+
}
135+
},
136+
initialData: () => ({
137+
wow: true,
138+
}),
139+
}),
140+
),
141+
)
142+
143+
expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()
144+
})
145+
146+
it('TData should have undefined in the union when initialData is NOT provided', () => {
147+
const { data } = reactive(
148+
useQuery(
149+
queryOptions({
150+
queryKey: ['key'],
151+
queryFn: () => {
152+
return {
153+
wow: true,
154+
}
155+
},
156+
}),
157+
),
158+
)
159+
160+
expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()
161+
})
162+
163+
it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {
164+
const { data } = reactive(
165+
useQuery(
166+
queryOptions({
167+
queryKey: ['key'],
168+
queryFn: () => {
169+
return {
170+
wow: true,
171+
}
172+
},
173+
initialData: () => undefined as { wow: boolean } | undefined,
174+
}),
175+
),
176+
)
177+
178+
expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()
179+
})
180+
181+
it('TData should be narrowed after an isSuccess check when initialData is provided as a function which can return undefined', () => {
182+
const { data, isSuccess } = reactive(
183+
useQuery(
184+
queryOptions({
185+
queryKey: ['key'],
186+
queryFn: () => {
187+
return {
188+
wow: true,
189+
}
190+
},
191+
initialData: () => undefined as { wow: boolean } | undefined,
192+
}),
193+
),
194+
)
195+
196+
if (isSuccess) {
197+
expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()
198+
}
199+
})
200+
201+
it('data should not have undefined when initialData is provided', () => {
202+
const { data } = reactive(
203+
useQuery(
204+
queryOptions({
205+
queryKey: ['query-key'],
206+
initialData: 42,
207+
}),
208+
),
209+
)
210+
211+
expectTypeOf(data).toEqualTypeOf<number>()
212+
})
125213
})

packages/vue-query/src/__tests__/useQuery.test-d.ts

+11
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,17 @@ describe('useQuery', () => {
125125
expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()
126126
}
127127
})
128+
129+
it('data should not have undefined when initialData is provided', () => {
130+
const { data } = reactive(
131+
useQuery({
132+
queryKey: ['query-key'],
133+
initialData: 42,
134+
}),
135+
)
136+
137+
expectTypeOf(data).toEqualTypeOf<number>()
138+
})
128139
})
129140

130141
describe('custom composable', () => {

packages/vue-query/src/queryOptions.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ export function queryOptions<
1010
TData = TQueryFnData,
1111
TQueryKey extends QueryKey = QueryKey,
1212
>(
13-
options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
14-
): UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {
13+
options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
14+
): DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {
1515
queryKey: DataTag<TQueryKey, TQueryFnData, TError>
1616
}
1717

@@ -21,8 +21,8 @@ export function queryOptions<
2121
TData = TQueryFnData,
2222
TQueryKey extends QueryKey = QueryKey,
2323
>(
24-
options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
25-
): DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {
24+
options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
25+
): UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {
2626
queryKey: DataTag<TQueryKey, TQueryFnData, TError>
2727
}
2828

packages/vue-query/src/useQuery.ts

+9-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useBaseQuery } from './useBaseQuery'
33
import type {
44
DefaultError,
55
DefinedQueryObserverResult,
6+
InitialDataFunction,
67
QueryKey,
78
QueryObserverOptions,
89
} from '@tanstack/query-core'
@@ -64,7 +65,10 @@ export type UndefinedInitialQueryOptions<
6465
TData = TQueryFnData,
6566
TQueryKey extends QueryKey = QueryKey,
6667
> = UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey> & {
67-
initialData?: undefined | (() => undefined)
68+
initialData?:
69+
| undefined
70+
| InitialDataFunction<NonUndefinedGuard<TQueryFnData>>
71+
| NonUndefinedGuard<TQueryFnData>
6872
}
6973

7074
export type DefinedInitialQueryOptions<
@@ -95,19 +99,19 @@ export function useQuery<
9599
TData = TQueryFnData,
96100
TQueryKey extends QueryKey = QueryKey,
97101
>(
98-
options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
102+
options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
99103
queryClient?: QueryClient,
100-
): UseQueryReturnType<TData, TError>
104+
): UseQueryDefinedReturnType<TData, TError>
101105

102106
export function useQuery<
103107
TQueryFnData = unknown,
104108
TError = DefaultError,
105109
TData = TQueryFnData,
106110
TQueryKey extends QueryKey = QueryKey,
107111
>(
108-
options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
112+
options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
109113
queryClient?: QueryClient,
110-
): UseQueryDefinedReturnType<TData, TError>
114+
): UseQueryReturnType<TData, TError>
111115

112116
export function useQuery<
113117
TQueryFnData = unknown,

0 commit comments

Comments
 (0)