Skip to content

Commit 891ec87

Browse files
committed
fix: typings of select query (#12)
1 parent eb2ccfe commit 891ec87

File tree

6 files changed

+285
-73
lines changed

6 files changed

+285
-73
lines changed

src/mobx-query-client.types.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ import {
88
import { MobxInfiniteQuery } from './mobx-inifinite-query';
99
import { MobxMutation } from './mobx-mutation';
1010
import { MobxMutationFeatures } from './mobx-mutation.types';
11-
import { MobxQuery } from './mobx-query';
1211
import type { MobxQueryClient } from './mobx-query-client';
13-
import { MobxQueryFeatures } from './mobx-query.types';
12+
import { AnyMobxQuery, MobxQueryFeatures } from './mobx-query.types';
1413

1514
export type IQueryClient = {
1615
[K in keyof QueryClient]: QueryClient[K];
@@ -31,10 +30,10 @@ export interface MobxDefaultOptions<TError = DefaultError>
3130
}
3231

3332
export interface MobxQueryClientHooks {
34-
onQueryInit?: (query: MobxQuery<any, any, any>) => void;
33+
onQueryInit?: (query: AnyMobxQuery) => void;
3534
onInfiniteQueryInit?: (query: MobxInfiniteQuery<any, any, any, any>) => void;
3635
onMutationInit?: (query: MobxMutation<any, any, any, any>) => void;
37-
onQueryDestroy?: (query: MobxQuery<any, any, any>) => void;
36+
onQueryDestroy?: (query: AnyMobxQuery) => void;
3837
onInfiniteQueryDestroy?: (
3938
query: MobxInfiniteQuery<any, any, any, any>,
4039
) => void;

src/mobx-query.test.ts

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,15 @@ import {
1818
runInAction,
1919
when,
2020
} from 'mobx';
21-
import { afterEach, describe, expect, it, test, vi } from 'vitest';
21+
import {
22+
afterEach,
23+
describe,
24+
expect,
25+
expectTypeOf,
26+
it,
27+
test,
28+
vi,
29+
} from 'vitest';
2230
import { waitAsync } from 'yummies/async';
2331

2432
import { MobxQuery } from './mobx-query';
@@ -32,10 +40,12 @@ import {
3240
import { createQuery } from './preset';
3341

3442
class MobxQueryMock<
35-
TData,
43+
TQueryFnData = unknown,
3644
TError = DefaultError,
37-
TQueryKey extends QueryKey = any,
38-
> extends MobxQuery<TData, TError, TQueryKey> {
45+
TData = TQueryFnData,
46+
TQueryData = TQueryFnData,
47+
TQueryKey extends QueryKey = QueryKey,
48+
> extends MobxQuery<TQueryFnData, TError, TData, TQueryData, TQueryKey> {
3949
spies = {
4050
queryFn: null as unknown as ReturnType<typeof vi.fn>,
4151
setData: vi.fn(),
@@ -48,7 +58,10 @@ class MobxQueryMock<
4858
};
4959

5060
constructor(
51-
options: Omit<MobxQueryConfig<TData, TError, TQueryKey>, 'queryClient'>,
61+
options: Omit<
62+
MobxQueryConfig<TQueryFnData, TError, TData, TQueryData, TQueryKey>,
63+
'queryClient'
64+
>,
5265
queryClient?: QueryClient,
5366
) {
5467
super({
@@ -86,18 +99,33 @@ class MobxQueryMock<
8699

87100
update(
88101
options:
89-
| MobxQueryUpdateOptions<TData, TError, TQueryKey>
90-
| MobxQueryDynamicOptions<TData, TError, TQueryKey>,
102+
| MobxQueryUpdateOptions<
103+
TQueryFnData,
104+
TError,
105+
TData,
106+
TQueryData,
107+
TQueryKey
108+
>
109+
| MobxQueryDynamicOptions<
110+
TQueryFnData,
111+
TError,
112+
TData,
113+
TQueryData,
114+
TQueryKey
115+
>,
91116
): void {
92117
const result = super.update(options);
93118
this.spies.update.mockReturnValue(result)(options);
94119
return result;
95120
}
96121

97122
setData(
98-
updater: Updater<NoInfer<TData> | undefined, NoInfer<TData> | undefined>,
99-
options?: SetDataOptions | undefined,
100-
): TData | undefined {
123+
updater: Updater<
124+
NoInfer<TQueryFnData> | undefined,
125+
NoInfer<TQueryFnData> | undefined
126+
>,
127+
options?: SetDataOptions,
128+
): TQueryFnData | undefined {
101129
const result = super.setData(updater, options);
102130
this.spies.setData.mockReturnValue(result)(updater, options);
103131
return result;
@@ -2216,4 +2244,33 @@ describe('MobxQuery', () => {
22162244
expect(error?.message).toBe('MobxQueryError');
22172245
});
22182246
});
2247+
2248+
it('select type bugfix (#12 issue)', async () => {
2249+
const data = [
2250+
{
2251+
address: 'a1',
2252+
name: 'Foo',
2253+
},
2254+
{
2255+
address: 'b1',
2256+
name: 'Bar',
2257+
},
2258+
];
2259+
2260+
const queryWithSelect = new MobxQuery({
2261+
queryClient: new MobxQueryClient(),
2262+
queryKey: ['a'],
2263+
queryFn: () => data,
2264+
select: (data) => {
2265+
return new Map(data.map((item) => [item.address, item]));
2266+
},
2267+
});
2268+
2269+
await when(() => !queryWithSelect.result.isLoading);
2270+
2271+
expectTypeOf(queryWithSelect.result.data).toEqualTypeOf<
2272+
undefined | Map<string, { address: string; name: string }>
2273+
>();
2274+
expect(queryWithSelect.result.data).toBeDefined();
2275+
});
22192276
});

src/mobx-query.ts

Lines changed: 83 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,26 @@ import {
3535
import { QueryOptionsParams } from './query-options';
3636

3737
export class MobxQuery<
38-
TData,
38+
TQueryFnData = unknown,
3939
TError = DefaultError,
40-
TQueryKey extends QueryKey = any,
40+
TData = TQueryFnData,
41+
TQueryData = TQueryFnData,
42+
TQueryKey extends QueryKey = QueryKey,
4143
> implements Disposable
4244
{
4345
protected abortController: AbortController;
4446
protected queryClient: AnyQueryClient;
4547

4648
protected _result: QueryObserverResult<TData, TError>;
4749

48-
options: MobxQueryOptions<TData, TError, TQueryKey>;
49-
queryObserver: QueryObserver<TData, TError, TData, TData, TQueryKey>;
50+
options: MobxQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>;
51+
queryObserver: QueryObserver<
52+
TQueryFnData,
53+
TError,
54+
TData,
55+
TQueryData,
56+
TQueryKey
57+
>;
5058

5159
isResultRequsted: boolean;
5260

@@ -57,25 +65,41 @@ export class MobxQuery<
5765
* in cases where the "enableOnDemand" option is enabled
5866
*/
5967
private holdedEnabledOption: MobxQueryOptions<
60-
TData,
68+
TQueryFnData,
6169
TError,
70+
TData,
71+
TQueryData,
6272
TQueryKey
6373
>['enabled'];
6474
private _observerSubscription?: VoidFunction;
6575
private hooks?: MobxQueryClientHooks;
6676

67-
protected config: MobxQueryConfig<TData, TError, TQueryKey>;
77+
protected config: MobxQueryConfig<
78+
TQueryFnData,
79+
TError,
80+
TData,
81+
TQueryData,
82+
TQueryKey
83+
>;
6884

69-
constructor(config: MobxQueryConfig<TData, TError, TQueryKey>);
85+
constructor(
86+
config: MobxQueryConfig<TQueryFnData, TError, TData, TQueryData, TQueryKey>,
87+
);
7088
constructor(
7189
queryClient: AnyQueryClient,
72-
config: () => QueryOptionsParams<TData, TError, TQueryKey>,
90+
config: () => QueryOptionsParams<
91+
TQueryFnData,
92+
TError,
93+
TData,
94+
TQueryData,
95+
TQueryKey
96+
>,
7397
);
7498

7599
constructor(...args: any[]) {
76100
const [queryClient, config]: [
77101
AnyQueryClient,
78-
QueryOptionsParams<TData, TError, TQueryKey>,
102+
QueryOptionsParams<TQueryFnData, TError, TData, TQueryData, TQueryKey>,
79103
] =
80104
args.length === 2 ? [args[0], args[1]()] : [args[0].queryClient, args[0]];
81105
const {
@@ -145,10 +169,13 @@ export class MobxQuery<
145169
queryClient.getDefaultOptions().queries?.notifyOnChangeProps ??
146170
'all';
147171

148-
this.queryObserver = new QueryObserver(
149-
queryClient as QueryClient,
150-
this.options,
151-
);
172+
this.queryObserver = new QueryObserver<
173+
TQueryFnData,
174+
TError,
175+
TData,
176+
TQueryData,
177+
TQueryKey
178+
>(queryClient as QueryClient, this.options);
152179

153180
this.updateResult(this.queryObserver.getOptimisticResult(this.options));
154181

@@ -209,7 +236,13 @@ export class MobxQuery<
209236

210237
protected createQueryHash(
211238
queryKey: any,
212-
options: MobxQueryOptions<TData, TError, TQueryKey>,
239+
options: MobxQueryOptions<
240+
TQueryFnData,
241+
TError,
242+
TData,
243+
TQueryData,
244+
TQueryKey
245+
>,
213246
) {
214247
if (options.queryKeyHashFn) {
215248
return options.queryKeyHashFn(queryKey);
@@ -219,10 +252,13 @@ export class MobxQuery<
219252
}
220253

221254
setData(
222-
updater: Updater<NoInfer<TData> | undefined, NoInfer<TData> | undefined>,
255+
updater: Updater<
256+
NoInfer<TQueryFnData> | undefined,
257+
NoInfer<TQueryFnData> | undefined
258+
>,
223259
options?: SetDataOptions,
224260
) {
225-
return this.queryClient.setQueryData<TData>(
261+
return this.queryClient.setQueryData<TQueryFnData>(
226262
this.options.queryKey,
227263
updater,
228264
options,
@@ -231,9 +267,23 @@ export class MobxQuery<
231267

232268
update(
233269
optionsUpdate:
234-
| Partial<MobxQueryOptions<TData, TError, TQueryKey>>
235-
| MobxQueryUpdateOptions<TData, TError, TQueryKey>
236-
| MobxQueryDynamicOptions<TData, TError, TQueryKey>,
270+
| Partial<
271+
MobxQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>
272+
>
273+
| MobxQueryUpdateOptions<
274+
TQueryFnData,
275+
TError,
276+
TData,
277+
TQueryData,
278+
TQueryKey
279+
>
280+
| MobxQueryDynamicOptions<
281+
TQueryFnData,
282+
TError,
283+
TData,
284+
TQueryData,
285+
TQueryKey
286+
>,
237287
) {
238288
if (this.abortController.signal.aborted) {
239289
return;
@@ -256,7 +306,13 @@ export class MobxQuery<
256306
private enableHolder = () => false;
257307

258308
private processOptions = (
259-
options: MobxQueryOptions<TData, TError, TQueryKey>,
309+
options: MobxQueryOptions<
310+
TQueryFnData,
311+
TError,
312+
TData,
313+
TQueryData,
314+
TQueryKey
315+
>,
260316
) => {
261317
options.queryHash = this.createQueryHash(options.queryKey, options);
262318

@@ -379,7 +435,13 @@ export class MobxQuery<
379435
async start({
380436
cancelRefetch,
381437
...params
382-
}: MobxQueryStartParams<TData, TError, TQueryKey> = {}) {
438+
}: MobxQueryStartParams<
439+
TQueryFnData,
440+
TError,
441+
TData,
442+
TQueryData,
443+
TQueryKey
444+
> = {}) {
383445
this.update({ ...params });
384446

385447
await this.refetch({ cancelRefetch });

0 commit comments

Comments
 (0)