Skip to content

Commit 0fa1f01

Browse files
feat(types): Include optional TError on DataTag (#8361)
* Include TError on DataTag so that getQueryState can infer the error type correctly * ci: apply automated fixes * Add type case to QueryFilters tests * Remove redudant comment * TInferredError * Fix Default TError in query filters * Move to UnsetMarker and add type changes to a few missed datatag usages * Fixed wasting Dominik's time * Force build * Undo --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent f245792 commit 0fa1f01

File tree

8 files changed

+88
-20
lines changed

8 files changed

+88
-20
lines changed

packages/query-core/src/__tests__/queryClient.test-d.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { describe, expectTypeOf, it } from 'vitest'
22
import { QueryClient } from '../queryClient'
3+
import type { QueryState } from '../query'
34
import type { DataTag, InfiniteData, QueryKey } from '../types'
45

56
describe('getQueryData', () => {
@@ -101,6 +102,35 @@ describe('setQueryData', () => {
101102
})
102103
})
103104

105+
describe('getQueryState', () => {
106+
it('should be loose typed without tag', () => {
107+
const queryKey = ['key'] as const
108+
const queryClient = new QueryClient()
109+
const data = queryClient.getQueryState(queryKey)
110+
111+
expectTypeOf(data).toEqualTypeOf<QueryState<unknown, Error> | undefined>()
112+
})
113+
114+
it('should be typed if key is tagged', () => {
115+
const queryKey = ['key'] as DataTag<Array<string>, number>
116+
const queryClient = new QueryClient()
117+
const data = queryClient.getQueryState(queryKey)
118+
119+
expectTypeOf(data).toEqualTypeOf<QueryState<number, Error> | undefined>()
120+
})
121+
122+
it('should be typed including error if key is tagged', () => {
123+
type CustomError = Error & { customError: string }
124+
const queryKey = ['key'] as DataTag<Array<string>, number, CustomError>
125+
const queryClient = new QueryClient()
126+
const data = queryClient.getQueryState(queryKey)
127+
128+
expectTypeOf(data).toEqualTypeOf<
129+
QueryState<number, CustomError> | undefined
130+
>()
131+
})
132+
})
133+
104134
describe('fetchInfiniteQuery', () => {
105135
it('should allow passing pages', async () => {
106136
const data = await new QueryClient().fetchInfiniteQuery({

packages/query-core/src/__tests__/utils.test-d.tsx

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ import type { DataTag } from '../types'
66
describe('QueryFilters', () => {
77
it('should be typed if generics are passed', () => {
88
type TData = { a: number; b: string }
9-
type TError = { message: string }
109

11-
const a: QueryFilters<TData, TError> = {
10+
const a: QueryFilters<TData> = {
1211
predicate(query) {
1312
expectTypeOf(query.setData({ a: 1, b: '1' })).toEqualTypeOf<TData>()
1413
return true
@@ -22,7 +21,28 @@ describe('QueryFilters', () => {
2221
expectTypeOf(data).toEqualTypeOf<TData | undefined>()
2322

2423
const error = queryClient.getQueryState(a.queryKey!)?.error
25-
expectTypeOf(error).toEqualTypeOf<Error | null | undefined>() // maybe one day this can return TError
24+
expectTypeOf(error).toEqualTypeOf<Error | null | undefined>()
25+
})
26+
27+
it('should be typed if generics are passed including an error type', () => {
28+
type TData = { a: number; b: string }
29+
type TError = Error & { message: string }
30+
31+
const a: QueryFilters<TData, TError> = {
32+
predicate(query) {
33+
expectTypeOf(query.setData({ a: 1, b: '1' })).toEqualTypeOf<TData>()
34+
return true
35+
},
36+
queryKey: ['key'] as DataTag<undefined, TData, TError>,
37+
}
38+
39+
const queryClient = new QueryClient()
40+
41+
const data = queryClient.getQueryData(a.queryKey!)
42+
expectTypeOf(data).toEqualTypeOf<TData | undefined>()
43+
44+
const error = queryClient.getQueryState(a.queryKey!)?.error
45+
expectTypeOf(error).toEqualTypeOf<TError | null | undefined>()
2646
})
2747

2848
it('should be loose typed if generics are defaults', () => {

packages/query-core/src/queryClient.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import type {
3939
RefetchQueryFilters,
4040
ResetOptions,
4141
SetDataOptions,
42+
UnsetMarker,
4243
} from './types'
4344
import type { QueryState } from './query'
4445
import type { MutationFilters, QueryFilters, Updater } from './utils'
@@ -119,7 +120,8 @@ export class QueryClient {
119120
TTaggedQueryKey extends QueryKey = QueryKey,
120121
TInferredQueryFnData = TTaggedQueryKey extends DataTag<
121122
unknown,
122-
infer TaggedValue
123+
infer TaggedValue,
124+
unknown
123125
>
124126
? TaggedValue
125127
: TQueryFnData,
@@ -169,7 +171,8 @@ export class QueryClient {
169171
TTaggedQueryKey extends QueryKey = QueryKey,
170172
TInferredQueryFnData = TTaggedQueryKey extends DataTag<
171173
unknown,
172-
infer TaggedValue
174+
infer TaggedValue,
175+
unknown
173176
>
174177
? TaggedValue
175178
: TQueryFnData,
@@ -225,16 +228,27 @@ export class QueryClient {
225228
TTaggedQueryKey extends QueryKey = QueryKey,
226229
TInferredQueryFnData = TTaggedQueryKey extends DataTag<
227230
unknown,
228-
infer TaggedValue
231+
infer TaggedValue,
232+
unknown
229233
>
230234
? TaggedValue
231235
: TQueryFnData,
236+
TInferredError = TTaggedQueryKey extends DataTag<
237+
unknown,
238+
unknown,
239+
infer TaggedError
240+
>
241+
? TaggedError extends UnsetMarker
242+
? TError
243+
: TaggedError
244+
: TError,
232245
>(
233246
queryKey: TTaggedQueryKey,
234-
): QueryState<TInferredQueryFnData, TError> | undefined {
247+
): QueryState<TInferredQueryFnData, TInferredError> | undefined {
235248
const options = this.defaultQueryOptions({ queryKey })
236-
return this.#queryCache.get<TInferredQueryFnData, TError>(options.queryHash)
237-
?.state
249+
return this.#queryCache.get<TInferredQueryFnData, TInferredError>(
250+
options.queryHash,
251+
)?.state
238252
}
239253

240254
removeQueries(filters?: QueryFilters): void {

packages/query-core/src/types.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,12 @@ export type DefaultError = Register extends {
4343
export type QueryKey = ReadonlyArray<unknown>
4444

4545
export declare const dataTagSymbol: unique symbol
46-
export type DataTag<TType, TValue> = TType & {
46+
export declare const dataTagErrorSymbol: unique symbol
47+
export declare const unsetMarker: unique symbol
48+
export type UnsetMarker = typeof unsetMarker
49+
export type DataTag<TType, TValue, TError = UnsetMarker> = TType & {
4750
[dataTagSymbol]: TValue
51+
[dataTagErrorSymbol]: TError
4852
}
4953

5054
export type QueryFunction<
@@ -536,7 +540,7 @@ export interface RefetchOptions extends ResultOptions {
536540

537541
export interface InvalidateQueryFilters<
538542
TQueryFnData = unknown,
539-
TError = Error,
543+
TError = DefaultError,
540544
TData = TQueryFnData,
541545
TQueryKey extends QueryKey = QueryKey,
542546
> extends QueryFilters<TQueryFnData, TError, TData, TQueryKey> {
@@ -545,7 +549,7 @@ export interface InvalidateQueryFilters<
545549

546550
export interface RefetchQueryFilters<
547551
TQueryFnData = unknown,
548-
TError = Error,
552+
TError = DefaultError,
549553
TData = TQueryFnData,
550554
TQueryKey extends QueryKey = QueryKey,
551555
> extends QueryFilters<TQueryFnData, TError, TData, TQueryKey> {}

packages/query-core/src/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import type { FetchOptions, Query } from './query'
1717

1818
export interface QueryFilters<
1919
TQueryFnData = unknown,
20-
TError = Error,
20+
TError = DefaultError,
2121
TData = TQueryFnData,
2222
TQueryKey extends QueryKey = QueryKey,
2323
> {
@@ -38,7 +38,7 @@ export interface QueryFilters<
3838
*/
3939
queryKey?: unknown extends TQueryFnData
4040
? QueryKey
41-
: QueryKey & DataTag<unknown, TQueryFnData>
41+
: QueryKey & DataTag<unknown, TQueryFnData, TError>
4242
/**
4343
* Include or exclude stale queries
4444
*/

packages/vue-query/src/infiniteQueryOptions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export function infiniteQueryOptions<
6565
TQueryKey,
6666
TPageParam
6767
> & {
68-
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>>
68+
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>
6969
}
7070

7171
export function infiniteQueryOptions<
@@ -89,7 +89,7 @@ export function infiniteQueryOptions<
8989
TQueryKey,
9090
TPageParam
9191
> & {
92-
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>>
92+
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>
9393
}
9494

9595
export function infiniteQueryOptions(options: unknown) {

packages/vue-query/src/queryClient.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export class QueryClient extends QC {
5757
getQueryData<TData = unknown, TTaggedQueryKey extends QueryKey = QueryKey>(
5858
queryKey: TTaggedQueryKey,
5959
):
60-
| (TTaggedQueryKey extends DataTag<unknown, infer TaggedValue>
60+
| (TTaggedQueryKey extends DataTag<unknown, infer TaggedValue, unknown>
6161
? TaggedValue
6262
: TData)
6363
| undefined
@@ -110,7 +110,7 @@ export class QueryClient extends QC {
110110
setQueryData<
111111
TQueryFnData,
112112
TTaggedQueryKey extends QueryKey,
113-
TData = TTaggedQueryKey extends DataTag<unknown, infer TaggedValue>
113+
TData = TTaggedQueryKey extends DataTag<unknown, infer TaggedValue, unknown>
114114
? TaggedValue
115115
: TQueryFnData,
116116
>(

packages/vue-query/src/queryOptions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export function queryOptions<
1212
>(
1313
options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
1414
): UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {
15-
queryKey: DataTag<TQueryKey, TQueryFnData>
15+
queryKey: DataTag<TQueryKey, TQueryFnData, TError>
1616
}
1717

1818
export function queryOptions<
@@ -23,7 +23,7 @@ export function queryOptions<
2323
>(
2424
options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
2525
): DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey> & {
26-
queryKey: DataTag<TQueryKey, TQueryFnData>
26+
queryKey: DataTag<TQueryKey, TQueryFnData, TError>
2727
}
2828

2929
export function queryOptions(options: unknown) {

0 commit comments

Comments
 (0)