@@ -11,42 +11,68 @@ import {
11
11
useQuery ,
12
12
useSuspenseQuery ,
13
13
queryOptions ,
14
- type DataTag ,
15
- type DefinedInitialDataOptions ,
16
- type UndefinedInitialDataOptions ,
17
14
} from "@tanstack/react-query" ;
18
15
import type { ClientMethod , FetchResponse , MaybeOptionalInit , Client as FetchClient } from "openapi-fetch" ;
19
16
import type { HttpMethod , MediaType , PathsWithMethod , RequiredKeysOf } from "openapi-typescript-helpers" ;
20
17
21
18
type InitWithUnknowns < Init > = Init & { [ key : string ] : unknown } ;
22
19
20
+ // biome-ignore lint/suspicious/noRedeclare: <https://stackoverflow.com/questions/52760509/typescript-returntype-of-overloaded-function>
21
+ type OverloadedReturnType < T > = T extends { ( ...args : any [ ] ) : infer R ; ( ...args : any [ ] ) : infer R }
22
+ ? R
23
+ : T extends ( ...args : any [ ] ) => infer R
24
+ ? R
25
+ : any ;
26
+
27
+ type OverloadedParameters < T > = T extends { ( ...args : infer P1 ) : any ; ( ...args : infer P2 ) : any }
28
+ ? P1
29
+ : T extends ( ...args : infer P ) => any
30
+ ? P
31
+ : never ;
32
+
23
33
export type QueryKey <
24
34
Paths extends Record < string , Record < HttpMethod , { } > > ,
25
35
Method extends HttpMethod ,
26
36
Path extends PathsWithMethod < Paths , Method > ,
27
37
> = readonly [ Method , Path , MaybeOptionalInit < Paths [ Path ] , Method > ] ;
28
38
29
- export type QueryOptionsObject < Paths extends Record < string , Record < HttpMethod , { } > > , Media extends MediaType > = <
39
+ export type QueryOptionsFunction < Paths extends Record < string , Record < HttpMethod , { } > > , Media extends MediaType > = <
30
40
Method extends HttpMethod ,
31
41
Path extends PathsWithMethod < Paths , Method > ,
32
42
Init extends MaybeOptionalInit < Paths [ Path ] , Method > ,
33
43
Response extends Required < FetchResponse < Paths [ Path ] [ Method ] , Init , Media > > , // note: Required is used to avoid repeating NonNullable in UseQuery types
34
44
Options extends Omit <
35
45
UseQueryOptions < Response [ "data" ] , Response [ "error" ] , Response [ "data" ] , QueryKey < Paths , Method , Path > > ,
36
- "queryKey" | "queryFn" | "initialData"
46
+ "queryKey" | "queryFn"
47
+ > ,
48
+ > (
49
+ method : Method ,
50
+ path : Path ,
51
+ ...[ init , options ] : RequiredKeysOf < Init > extends never
52
+ ? [ InitWithUnknowns < Init > ?, Options ?]
53
+ : [ InitWithUnknowns < Init > , Options ?]
54
+ ) => UseQueryOptions < Response [ "data" ] , Response [ "error" ] , Response [ "data" ] , QueryKey < Paths , Method , Path > > ;
55
+
56
+ export type QueryOptionsObject < Paths extends Record < string , Record < HttpMethod , { } > > , Media extends MediaType > = <
57
+ Method extends HttpMethod ,
58
+ Path extends PathsWithMethod < Paths , Method > ,
59
+ Init extends MaybeOptionalInit < Paths [ Path ] , Method > ,
60
+ Response extends Required < FetchResponse < Paths [ Path ] [ Method ] , Init , Media > > , // note: Required is used to avoid repeating NonNullable in UseQuery types
61
+ Options extends Omit <
62
+ OverloadedParameters <
63
+ typeof queryOptions < Response [ "data" ] , Response [ "error" ] , Response [ "data" ] , QueryKey < Paths , Method , Path > >
64
+ > [ 0 ] ,
65
+ "queryKey" | "queryFn"
37
66
> ,
38
67
> (
39
68
method : Method ,
40
69
path : Path ,
41
70
...[ init , options ] : RequiredKeysOf < Init > extends never
42
71
? [ InitWithUnknowns < Init > ?, Options ?]
43
72
: [ InitWithUnknowns < Init > , Options ?]
44
- ) => (
45
- | DefinedInitialDataOptions < Response [ "data" ] , Response [ "error" ] , Response [ "data" ] , QueryKey < Paths , Method , Path > >
46
- | UndefinedInitialDataOptions < Response [ "data" ] , Response [ "error" ] , Response [ "data" ] , QueryKey < Paths , Method , Path > >
47
- ) & {
48
- queryKey : DataTag < QueryKey < Paths , Method , Path > , Response [ "data" ] > ;
49
- } ;
73
+ ) => OverloadedReturnType <
74
+ typeof queryOptions < Response [ "data" ] , Response [ "error" ] , Response [ "data" ] , QueryKey < Paths , Method , Path > >
75
+ > ;
50
76
51
77
export type UseQueryMethod < Paths extends Record < string , Record < HttpMethod , { } > > , Media extends MediaType > = <
52
78
Method extends HttpMethod ,
@@ -119,19 +145,24 @@ export default function createClient<Paths extends {}, Media extends MediaType =
119
145
return data ;
120
146
} ;
121
147
122
- const queryOptionsObject : QueryOptionsObject < Paths , Media > = ( method , path , ...[ init , options ] ) =>
123
- queryOptions ( {
124
- queryKey : [ method , path , init as InitWithUnknowns < typeof init > ] as const ,
125
- queryFn,
126
- ...options ,
127
- } ) ;
148
+ const queryOptionsParams : QueryOptionsFunction < Paths , Media > = ( method , path , ...[ init , options ] ) => ( {
149
+ queryKey : [ method , path , init as InitWithUnknowns < typeof init > ] as const ,
150
+ queryFn,
151
+ ...options ,
152
+ } ) ;
128
153
129
154
return {
130
- queryOptions : queryOptionsObject ,
155
+ queryOptions : ( method , path , ...[ init , options ] ) =>
156
+ queryOptions ( {
157
+ queryKey : [ method , path , init as InitWithUnknowns < typeof init > ] as const ,
158
+ queryFn,
159
+ // TODO: find a way to avoid as any
160
+ ...( options as any ) ,
161
+ } ) ,
131
162
useQuery : ( method , path , ...[ init , options , queryClient ] ) =>
132
- useQuery ( queryOptionsObject ( method , path , init as InitWithUnknowns < typeof init > , options ) , queryClient ) ,
163
+ useQuery ( queryOptionsParams ( method , path , init as InitWithUnknowns < typeof init > , options ) , queryClient ) ,
133
164
useSuspenseQuery : ( method , path , ...[ init , options , queryClient ] ) =>
134
- useSuspenseQuery ( queryOptionsObject ( method , path , init as InitWithUnknowns < typeof init > , options ) , queryClient ) ,
165
+ useSuspenseQuery ( queryOptionsParams ( method , path , init as InitWithUnknowns < typeof init > , options ) , queryClient ) ,
135
166
useMutation : ( method , path , options , queryClient ) =>
136
167
useMutation (
137
168
{
0 commit comments