Skip to content

Commit 53c901d

Browse files
committed
fix(angular-query-experimental): typings for injectQueries should now behave properly
1 parent e474f73 commit 53c901d

File tree

2 files changed

+290
-102
lines changed

2 files changed

+290
-102
lines changed
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
import { describe, expectTypeOf, it } from 'vitest'
2+
import { skipToken } from '..'
3+
import { injectQueries } from '../inject-queries'
4+
import { queryOptions } from '../query-options'
5+
import type { CreateQueryOptions, CreateQueryResult, OmitKeyof } from '..'
6+
import type { Signal } from '@angular/core'
7+
8+
describe('InjectQueries config object overload', () => {
9+
it('TData should always be defined when initialData is provided as an object', () => {
10+
const query1 = {
11+
queryKey: ['key1'],
12+
queryFn: () => {
13+
return {
14+
wow: true,
15+
}
16+
},
17+
initialData: {
18+
wow: false,
19+
},
20+
}
21+
22+
const query2 = {
23+
queryKey: ['key2'],
24+
queryFn: () => 'Query Data',
25+
initialData: 'initial data',
26+
}
27+
28+
const query3 = {
29+
queryKey: ['key2'],
30+
queryFn: () => 'Query Data',
31+
}
32+
33+
const queryResults = injectQueries(() => ({
34+
queries: [query1, query2, query3],
35+
}))
36+
37+
const query1Data = queryResults()[0].data()
38+
const query2Data = queryResults()[1].data()
39+
const query3Data = queryResults()[2].data()
40+
41+
expectTypeOf(query1Data).toEqualTypeOf<{ wow: boolean }>()
42+
expectTypeOf(query2Data).toEqualTypeOf<string>()
43+
expectTypeOf(query3Data).toEqualTypeOf<string | undefined>()
44+
})
45+
46+
it('TData should be defined when passed through queryOptions', () => {
47+
const options = queryOptions({
48+
queryKey: ['key'],
49+
queryFn: () => {
50+
return {
51+
wow: true,
52+
}
53+
},
54+
initialData: {
55+
wow: true,
56+
},
57+
})
58+
const queryResults = injectQueries(() => ({ queries: [options] }))
59+
60+
const data = queryResults()[0].data()
61+
62+
expectTypeOf(data).toEqualTypeOf<{ wow: boolean }>()
63+
})
64+
65+
it('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into injectQuery', () => {
66+
const query1 = queryOptions({
67+
queryKey: ['key'],
68+
queryFn: () => Promise.resolve(1),
69+
select: (data) => data > 1,
70+
})
71+
72+
const query2 = {
73+
queryKey: ['key'],
74+
queryFn: () => Promise.resolve(1),
75+
select: (data: number) => data > 1,
76+
}
77+
78+
const queryResults = injectQueries(() => ({ queries: [query1, query2] }))
79+
const query1Data = queryResults()[0].data()
80+
const query2Data = queryResults()[1].data()
81+
82+
expectTypeOf(query1Data).toEqualTypeOf<boolean | undefined>()
83+
expectTypeOf(query2Data).toEqualTypeOf<boolean | undefined>()
84+
})
85+
86+
it('TData should have undefined in the union when initialData is provided as a function which can return undefined', () => {
87+
const queryResults = injectQueries(() => ({
88+
queries: [
89+
{
90+
queryKey: ['key'],
91+
queryFn: () => {
92+
return {
93+
wow: true,
94+
}
95+
},
96+
initialData: () => undefined as { wow: boolean } | undefined,
97+
},
98+
],
99+
}))
100+
101+
const data = queryResults()[0].data()
102+
103+
expectTypeOf(data).toEqualTypeOf<{ wow: boolean } | undefined>()
104+
})
105+
106+
describe('custom injectable', () => {
107+
it('should allow custom hooks using UseQueryOptions', () => {
108+
type Data = string
109+
110+
const injectCustomQueries = (
111+
options?: OmitKeyof<CreateQueryOptions<Data>, 'queryKey' | 'queryFn'>,
112+
) => {
113+
return injectQueries(() => ({
114+
queries: [
115+
{
116+
...options,
117+
queryKey: ['todos-key'],
118+
queryFn: () => Promise.resolve('data'),
119+
},
120+
],
121+
}))
122+
}
123+
124+
const queryResults = injectCustomQueries()
125+
const data = queryResults()[0].data()
126+
127+
expectTypeOf(data).toEqualTypeOf<Data | undefined>()
128+
})
129+
})
130+
131+
it('TData should have correct type when conditional skipToken is passed', () => {
132+
const queryResults = injectQueries(() => ({
133+
queries: [
134+
{
135+
queryKey: ['withSkipToken'],
136+
queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5),
137+
},
138+
],
139+
}))
140+
141+
const firstResult = queryResults()[0]
142+
143+
expectTypeOf(firstResult).toEqualTypeOf<CreateQueryResult<number, Error>>()
144+
expectTypeOf(firstResult.data()).toEqualTypeOf<number | undefined>()
145+
})
146+
147+
it('should return correct data for dynamic queries with mixed result types', () => {
148+
const Queries1 = {
149+
get: () =>
150+
queryOptions({
151+
queryKey: ['key1'],
152+
queryFn: () => Promise.resolve(1),
153+
}),
154+
}
155+
const Queries2 = {
156+
get: () =>
157+
queryOptions({
158+
queryKey: ['key2'],
159+
queryFn: () => Promise.resolve(true),
160+
}),
161+
}
162+
163+
const queries1List = [1, 2, 3].map(() => ({ ...Queries1.get() }))
164+
const result = injectQueries(() => ({
165+
queries: [...queries1List, { ...Queries2.get() }],
166+
}))
167+
168+
expectTypeOf(result).branded.toEqualTypeOf<
169+
Signal<
170+
[
171+
...Array<CreateQueryResult<number, Error>>,
172+
CreateQueryResult<boolean, Error>,
173+
]
174+
>
175+
>()
176+
})
177+
})

0 commit comments

Comments
 (0)