Skip to content

Commit cd6ea9a

Browse files
authored
fix(angular-query): align mutation options to most recent react-query types (#9543)
* fix(angular-query): align mutation options to most recent react-query types * add tests
1 parent 34657e5 commit cd6ea9a

File tree

6 files changed

+592
-37
lines changed

6 files changed

+592
-37
lines changed
Lines changed: 184 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,199 @@
1-
import { assertType, describe, expectTypeOf, test } from 'vitest'
2-
import { mutationOptions } from '../mutation-options'
1+
import { assertType, describe, expectTypeOf, it } from 'vitest'
2+
import { QueryClient } from '@tanstack/query-core'
3+
import {
4+
injectIsMutating,
5+
injectMutation,
6+
injectMutationState,
7+
mutationOptions,
8+
} from '..'
9+
import type {
10+
DefaultError,
11+
MutationState,
12+
WithRequired,
13+
} from '@tanstack/query-core'
14+
import type { CreateMutationOptions, CreateMutationResult } from '../types'
315

416
describe('mutationOptions', () => {
5-
test('should not allow excess properties', () => {
6-
assertType<Parameters<typeof mutationOptions>>([
7-
{
8-
mutationFn: () => Promise.resolve(5),
9-
mutationKey: ['key'],
10-
// @ts-expect-error this is a good error, because onMutates does not exist!
11-
onMutates: 1000,
17+
it('should not allow excess properties', () => {
18+
// @ts-expect-error this is a good error, because onMutates does not exist!
19+
mutationOptions({
20+
mutationFn: () => Promise.resolve(5),
21+
mutationKey: ['key'],
22+
onMutates: 1000,
23+
onSuccess: (data) => {
24+
expectTypeOf(data).toEqualTypeOf<number>()
1225
},
13-
])
14-
assertType<Parameters<typeof mutationOptions>>([
15-
{
16-
mutationFn: () => Promise.resolve(5),
17-
mutationKey: ['key'],
18-
// @ts-expect-error this is a good error, because onMutates does not exist!
19-
onMutates: 1000,
26+
})
27+
})
28+
29+
it('should infer types for callbacks', () => {
30+
mutationOptions({
31+
mutationFn: () => Promise.resolve(5),
32+
mutationKey: ['key'],
33+
onSuccess: (data) => {
34+
expectTypeOf(data).toEqualTypeOf<number>()
2035
},
21-
])
36+
})
2237
})
2338

24-
test('should infer types for callbacks', () => {
39+
it('should infer types for onError callback', () => {
2540
mutationOptions({
41+
mutationFn: () => {
42+
throw new Error('fail')
43+
},
44+
mutationKey: ['key'],
45+
onError: (error) => {
46+
expectTypeOf(error).toEqualTypeOf<DefaultError>()
47+
},
48+
})
49+
})
50+
51+
it('should infer types for variables', () => {
52+
mutationOptions<number, DefaultError, { id: string }>({
53+
mutationFn: (vars) => {
54+
expectTypeOf(vars).toEqualTypeOf<{ id: string }>()
55+
return Promise.resolve(5)
56+
},
57+
mutationKey: ['with-vars'],
58+
})
59+
})
60+
61+
it('should infer context type correctly', () => {
62+
mutationOptions<number, DefaultError, void, { name: string }>({
2663
mutationFn: () => Promise.resolve(5),
2764
mutationKey: ['key'],
65+
onMutate: () => {
66+
return { name: 'context' }
67+
},
68+
onSuccess: (_data, _variables, context) => {
69+
expectTypeOf(context).toEqualTypeOf<{ name: string }>()
70+
},
71+
})
72+
})
73+
74+
it('should error if mutationFn return type mismatches TData', () => {
75+
assertType(
76+
mutationOptions<number>({
77+
// @ts-expect-error this is a good error, because return type is string, not number
78+
mutationFn: async () => Promise.resolve('wrong return'),
79+
}),
80+
)
81+
})
82+
83+
it('should allow mutationKey to be omitted', () => {
84+
return mutationOptions({
85+
mutationFn: () => Promise.resolve(123),
2886
onSuccess: (data) => {
2987
expectTypeOf(data).toEqualTypeOf<number>()
3088
},
3189
})
3290
})
91+
92+
it('should infer all types when not explicitly provided', () => {
93+
expectTypeOf(
94+
mutationOptions({
95+
mutationFn: (id: string) => Promise.resolve(id.length),
96+
mutationKey: ['key'],
97+
onSuccess: (data) => {
98+
expectTypeOf(data).toEqualTypeOf<number>()
99+
},
100+
}),
101+
).toEqualTypeOf<
102+
WithRequired<
103+
CreateMutationOptions<number, DefaultError, string>,
104+
'mutationKey'
105+
>
106+
>()
107+
expectTypeOf(
108+
mutationOptions({
109+
mutationFn: (id: string) => Promise.resolve(id.length),
110+
onSuccess: (data) => {
111+
expectTypeOf(data).toEqualTypeOf<number>()
112+
},
113+
}),
114+
).toEqualTypeOf<
115+
Omit<CreateMutationOptions<number, DefaultError, string>, 'mutationKey'>
116+
>()
117+
})
118+
119+
it('should infer types when used with injectMutation', () => {
120+
const mutation = injectMutation(() =>
121+
mutationOptions({
122+
mutationKey: ['key'],
123+
mutationFn: () => Promise.resolve('data'),
124+
onSuccess: (data) => {
125+
expectTypeOf(data).toEqualTypeOf<string>()
126+
},
127+
}),
128+
)
129+
expectTypeOf(mutation).toEqualTypeOf<
130+
CreateMutationResult<string, DefaultError, void, unknown>
131+
>()
132+
133+
injectMutation(
134+
// should allow when used with injectMutation without mutationKey
135+
() =>
136+
mutationOptions({
137+
mutationFn: () => Promise.resolve('data'),
138+
onSuccess: (data) => {
139+
expectTypeOf(data).toEqualTypeOf<string>()
140+
},
141+
}),
142+
)
143+
})
144+
145+
it('should infer types when used with injectIsMutating', () => {
146+
const isMutating = injectIsMutating(
147+
mutationOptions({
148+
mutationKey: ['key'],
149+
mutationFn: () => Promise.resolve(5),
150+
}),
151+
)
152+
expectTypeOf(isMutating()).toEqualTypeOf<number>()
153+
154+
injectIsMutating(
155+
// @ts-expect-error filters should have mutationKey
156+
mutationOptions({
157+
mutationFn: () => Promise.resolve(5),
158+
}),
159+
)
160+
})
161+
162+
it('should infer types when used with queryClient.isMutating', () => {
163+
const queryClient = new QueryClient()
164+
165+
const isMutating = queryClient.isMutating(
166+
mutationOptions({
167+
mutationKey: ['key'],
168+
mutationFn: () => Promise.resolve(5),
169+
}),
170+
)
171+
expectTypeOf(isMutating).toEqualTypeOf<number>()
172+
173+
queryClient.isMutating(
174+
// @ts-expect-error filters should have mutationKey
175+
mutationOptions({
176+
mutationFn: () => Promise.resolve(5),
177+
}),
178+
)
179+
})
180+
181+
it('should infer types when used with injectMutationState', () => {
182+
const mutationState = injectMutationState(() => ({
183+
filters: mutationOptions({
184+
mutationKey: ['key'],
185+
mutationFn: () => Promise.resolve(5),
186+
}),
187+
}))
188+
expectTypeOf(mutationState()).toEqualTypeOf<
189+
Array<MutationState<unknown, Error, unknown, unknown>>
190+
>()
191+
192+
injectMutationState({
193+
// @ts-expect-error filters should have mutationKey
194+
filters: mutationOptions({
195+
mutationFn: () => Promise.resolve(5),
196+
}),
197+
})
198+
})
33199
})

0 commit comments

Comments
 (0)