Skip to content

Commit df77d8c

Browse files
authored
test(svelte-query/createMutation): add type tests for generic type inference and callbacks (#10502)
1 parent 7ffa1ed commit df77d8c

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import { describe, expectTypeOf, it } from 'vitest'
2+
import { QueryClient } from '@tanstack/query-core'
3+
import { createMutation } from '../../src/index.js'
4+
import type { DefaultError } from '@tanstack/query-core'
5+
import type { CreateMutationResult } from '../../src/types.js'
6+
7+
describe('createMutation', () => {
8+
it('should infer TData from mutationFn return type', () => {
9+
const mutation = createMutation(() => ({
10+
mutationFn: () => Promise.resolve('data'),
11+
}))
12+
13+
expectTypeOf(mutation.data).toEqualTypeOf<string | undefined>()
14+
expectTypeOf(mutation.error).toEqualTypeOf<DefaultError | null>()
15+
})
16+
17+
it('should infer TVariables from mutationFn parameter', () => {
18+
const mutation = createMutation(() => ({
19+
mutationFn: (vars: { id: string }) => Promise.resolve(vars.id),
20+
}))
21+
22+
expectTypeOf(mutation.mutate).toBeCallableWith({ id: '1' })
23+
expectTypeOf(mutation.data).toEqualTypeOf<string | undefined>()
24+
})
25+
26+
it('should infer TOnMutateResult from onMutate return type', () => {
27+
createMutation(() => ({
28+
mutationFn: () => Promise.resolve('data'),
29+
onMutate: () => {
30+
return { token: 'abc' }
31+
},
32+
onSuccess: (_data, _variables, onMutateResult) => {
33+
expectTypeOf(onMutateResult).toEqualTypeOf<{ token: string }>()
34+
},
35+
onError: (_error, _variables, onMutateResult) => {
36+
expectTypeOf(onMutateResult).toEqualTypeOf<
37+
{ token: string } | undefined
38+
>()
39+
},
40+
}))
41+
})
42+
43+
it('should allow explicit generic types', () => {
44+
const mutation = createMutation<string, Error, { id: number }>(() => ({
45+
mutationFn: (vars) => {
46+
expectTypeOf(vars).toEqualTypeOf<{ id: number }>()
47+
return Promise.resolve('result')
48+
},
49+
}))
50+
51+
expectTypeOf(mutation.data).toEqualTypeOf<string | undefined>()
52+
expectTypeOf(mutation.error).toEqualTypeOf<Error | null>()
53+
})
54+
55+
it('should return correct CreateMutationResult type', () => {
56+
const mutation = createMutation(() => ({
57+
mutationFn: () => Promise.resolve(42),
58+
}))
59+
60+
expectTypeOf(mutation).toEqualTypeOf<
61+
CreateMutationResult<number, DefaultError, void, unknown>
62+
>()
63+
})
64+
65+
it('should type mutateAsync with correct return type', () => {
66+
const mutation = createMutation(() => ({
67+
mutationFn: (id: string) => Promise.resolve(id.length),
68+
}))
69+
70+
expectTypeOf(mutation.mutateAsync).toBeCallableWith('test')
71+
expectTypeOf(mutation.mutateAsync('test')).toEqualTypeOf<Promise<number>>()
72+
})
73+
74+
it('should default TVariables to void when mutationFn has no parameters', () => {
75+
const mutation = createMutation(() => ({
76+
mutationFn: () => Promise.resolve('data'),
77+
}))
78+
79+
expectTypeOf(mutation.mutate).toBeCallableWith()
80+
})
81+
82+
it('should infer custom TError type', () => {
83+
class CustomError extends Error {
84+
code: number
85+
constructor(code: number) {
86+
super()
87+
this.code = code
88+
}
89+
}
90+
91+
const mutation = createMutation<string, CustomError>(() => ({
92+
mutationFn: () => Promise.resolve('data'),
93+
}))
94+
95+
expectTypeOf(mutation.error).toEqualTypeOf<CustomError | null>()
96+
expectTypeOf(mutation.data).toEqualTypeOf<string | undefined>()
97+
})
98+
99+
it('should infer types for onSettled callback', () => {
100+
createMutation(() => ({
101+
mutationFn: () => Promise.resolve(42),
102+
onSettled: (data, error, _variables, _onMutateResult) => {
103+
expectTypeOf(data).toEqualTypeOf<number | undefined>()
104+
expectTypeOf(error).toEqualTypeOf<DefaultError | null>()
105+
},
106+
}))
107+
})
108+
109+
it('should infer custom TError in onError callback', () => {
110+
class CustomError extends Error {
111+
code: number
112+
constructor(code: number) {
113+
super()
114+
this.code = code
115+
}
116+
}
117+
118+
createMutation<string, CustomError>(() => ({
119+
mutationFn: () => Promise.resolve('data'),
120+
onError: (error) => {
121+
expectTypeOf(error).toEqualTypeOf<CustomError>()
122+
},
123+
}))
124+
})
125+
126+
it('should accept queryClient as second argument', () => {
127+
const queryClient = new QueryClient()
128+
129+
const mutation = createMutation(
130+
() => ({
131+
mutationFn: () => Promise.resolve('data'),
132+
}),
133+
() => queryClient,
134+
)
135+
136+
expectTypeOf(mutation.data).toEqualTypeOf<string | undefined>()
137+
})
138+
})

0 commit comments

Comments
 (0)