Angular injectMutation: `onSuccess` loses type when `queryClient` is passed to `injectMutation`
Describe the bug
When the queryClient is passed in the injectMutation method, the return type of mutationFn is lost in the onSuccess method.
Your minimal, reproducible example
https://stackblitz.com/edit/stackblitz-starters-3zsk2e?file=test.ts
Steps to reproduce
import { injectMutation } from "@tanstack/angular-query-experimental";
// without queryClient
export const foo = injectMutation(() => ({
mutationFn: () => Promise.resolve({ foo: true }),
onSuccess: (result) => {
result.foo; // result: { foo: boolean; }
}
}));
// with queryClient
export const bar = injectMutation((queryClient) => ({
mutationFn: () => Promise.resolve({ bar: true }),
onSuccess: (result) => {
result.bar; // result: unknown
}
}));
Expected behavior
Even if the queryClient is passed, the return type of the mutationFn should remain in the onSuccess method.
How often does this bug happen?
Every time
Screenshots or Videos
No response
Platform
- OS: Windows 11
- Browser: Edge Chromium
- Version: 5.55.4
Tanstack Query adapter
angular-query
TanStack Query version
v5.55.4
TypeScript version
No response
Additional context
No response
Yeah this is a really frustrating issue. I either have to choose between just injecting the query client at the top level, or manually typing all parameters in the callback functions
Same here. Figured out, specifying the queryClient type does the trick for the moment. At least better than every method arguments.
injectMutation((client: QueryClient) => ({
}));
One could fix this by wrapping TData with NoInfer<TData> in the MutationOptions type of the core package at https://github.com/TanStack/query/blob/main/packages/query-core/src/types.ts#L1005, but that would be a breaking change for all adapters.
Hey, to all who reacted here: would you mind very much if I removed the client parameter? I am working towards a stable release and this isn't essential IMO.
Also the API to inject to inject the QueryClient became a bit less weird:
Now
client = inject(QueryClient) // This would result in an error before, but now works as expected
Before
client = injectQueryClient()
You can still use injectQueryClient and I think I'll keep it as convenience to easily pass a custom injector:
client = injectQueryClient({injector: this.injector})
If anybody wants to contribute the client parameter with types working properly we could re-add it.
This happens with the select function in injectQuery too
Reproduction as unit tests:
packages/angular-query-experimental/src/tests/inject-query.test-d.ts
test('should be possible to define a different TData than TQueryFnData using select with queryOptions spread into useQuery and passing queryClient', () => {
const options = queryOptions({
queryKey: ['key'],
queryFn: () => Promise.resolve(1),
})
const query = injectQuery((client) => ({
...options,
select: (data) => data > 1,
}))
expectTypeOf(query.data).toEqualTypeOf<Signal<boolean | undefined>>()
})
packages/angular-query-experimental/src/tests/inject-mutation-types.test-d.ts
test('onSuccess should receive the correct type when injectMutation passes queryClient', () => {
injectMutation((_queryClient) => ({
mutationFn: successMutator<{success: true}>,
onSuccess: (data) => {
expectTypeOf(data).toEqualTypeOf<{success: true}>()
}
}))
})