Skip to content

fix(react-query): preserve Mutation generics in useMutationState select callback#10464

Closed
mukeshdhadhariya wants to merge 1 commit intoTanStack:mainfrom
mukeshdhadhariya:main
Closed

fix(react-query): preserve Mutation generics in useMutationState select callback#10464
mukeshdhadhariya wants to merge 1 commit intoTanStack:mainfrom
mukeshdhadhariya:main

Conversation

@mukeshdhadhariya
Copy link
Copy Markdown

@mukeshdhadhariya mukeshdhadhariya commented Apr 12, 2026

Summary

#10463 issue

useMutationState currently loses type information in the select callback because Mutation is used without generics. This causes values like mutation.state.data to be inferred as unknown.

Changes

  • Made MutationStateOptions generic
  • Propagated generics to Mutation in the select callback
  • Updated getResult and useMutationState to support generics

Example

Before:

const result = useMutationState({
select: (mutation) => mutation.state.data
})
// result: unknown[]

After:

const result = useMutationState({
select: (mutation) => mutation.state.data
})
// result: number[]

Impact

  • Improves TypeScript type inference
  • No runtime behavior changes
  • Fully backward compatible

Motivation

This ensures that type information from core Mutation is preserved in the React adapter, improving developer experience when using select.

Summary by CodeRabbit

  • Refactor
    • Enhanced type inference in mutation state handling for improved developer experience and IDE support. Mutation state callbacks now receive fully typed mutation objects, enabling better autocomplete and type checking in TypeScript projects.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 12, 2026

📝 Walkthrough

Walkthrough

Updated useMutationState hook's generic type parameters from a single TResult to five parameters (TData, TError, TVariables, TContext, TResult), enabling full type inference for the select function and getResult operations. No runtime logic changes introduced.

Changes

Cohort / File(s) Summary
Type Parametrization Enhancement
packages/react-query/src/useMutationState.ts
Expanded generic signature from single TResult to five typed parameters (TData, TError, TVariables, TContext). Updated MutationStateOptions and select callback to receive fully typed Mutation objects. Propagated generics through getResult function options parameter.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 wiggles nose with delight
Five generics dance in harmony true,
Types now flow from me to you!
No more mysteries, all crystal clear—
Each mutation's data shines here! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: preserving Mutation generics in the useMutationState select callback to fix type inference issues.
Description check ✅ Passed The description covers the key aspects (summary, changes, examples, impact, motivation) but is missing the required checklist items and changeset status from the template.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/react-query/src/useMutationState.ts`:
- Around line 25-31: Update the generic defaults to preserve type precision:
import DefaultError from "@tanstack/query-core" and change the TError default
from unknown to DefaultError, and change the TResult default from the bare
MutationState to a parameterized MutationState<TData, TError, TVariables,
TContext> across the three declarations mentioned (MutationStateOptions,
getResult, and useMutationState) so that provided
TData/TError/TVariables/TContext flow into the result type and improve inference
for mutation.state.error in select callbacks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4c87af88-2335-4204-936f-7b25bdae9309

📥 Commits

Reviewing files that changed from the base of the PR and between 24de260 and 8104de3.

📒 Files selected for processing (1)
  • packages/react-query/src/useMutationState.ts

Comment on lines +25 to +31
type MutationStateOptions<
TData = unknown,
TError = unknown,
TVariables = unknown,
TContext = unknown,
TResult = MutationState
> = {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== query-core defaults =="
rg -n --type=ts -C2 'export interface MutationState<|export class Mutation<' packages/query-core/src/mutation.ts

echo
echo "== react adapter defaults =="
rg -n --type=ts -C2 'type MutationStateOptions<|function getResult<|export function useMutationState<' packages/react-query/src/useMutationState.ts

Repository: TanStack/query

Length of output: 560


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Full MutationStateOptions signature ==="
sed -n '25,35p' packages/react-query/src/useMutationState.ts

echo
echo "=== Full getResult signature ==="
sed -n '38,60p' packages/react-query/src/useMutationState.ts

echo
echo "=== Full useMutationState signature ==="
sed -n '62,75p' packages/react-query/src/useMutationState.ts

echo
echo "=== Current imports ==="
sed -n '1,15p' packages/react-query/src/useMutationState.ts

Repository: TanStack/query

Length of output: 1543


Default generic parameters regress type precision and break generic composition.

At lines 27, 40, and 64, TError = unknown diverges from query-core's TError = DefaultError, weakening type inference for mutation.state.error in select callbacks.

At lines 30, 43, and 67, TResult = MutationState (bare) is not parameterized. When callers provide TData, TError, TVariables, and TContext generics, they don't flow into the default return shape, breaking type safety for composed usage.

Apply the suggested fix across all three declarations (MutationStateOptions, getResult, useMutationState):

  • Import DefaultError from @tanstack/query-core
  • Change TError default from unknown to DefaultError
  • Change TResult default from MutationState to MutationState<TData, TError, TVariables, TContext>
Suggested type-level fix
 import type {
+  DefaultError,
   Mutation,
   MutationCache,
   MutationFilters,
   MutationState,
   QueryClient,
 } from '@tanstack/query-core'

 type MutationStateOptions<
   TData = unknown,
-  TError = unknown,
+  TError = DefaultError,
   TVariables = unknown,
   TContext = unknown,
-  TResult = MutationState
+  TResult = MutationState<TData, TError, TVariables, TContext>
 > = {
   filters?: MutationFilters
   select?: (
     mutation: Mutation<TData, TError, TVariables, TContext>
   ) => TResult
 }

 function getResult<
   TData = unknown,
-  TError = unknown,
+  TError = DefaultError,
   TVariables = unknown,
   TContext = unknown,
-  TResult = MutationState
+  TResult = MutationState<TData, TError, TVariables, TContext>
 >(
   mutationCache: MutationCache,
   options: MutationStateOptions<
     TData,
     TError,
     TVariables,
     TContext,
     TResult
   >,
 ): Array<TResult> {

 export function useMutationState<
   TData = unknown,
-  TError = unknown,
+  TError = DefaultError,
   TVariables = unknown,
   TContext = unknown,
-  TResult = MutationState
+  TResult = MutationState<TData, TError, TVariables, TContext>
 >(

Also applies to: lines 38–44, 62–68

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-query/src/useMutationState.ts` around lines 25 - 31, Update
the generic defaults to preserve type precision: import DefaultError from
"@tanstack/query-core" and change the TError default from unknown to
DefaultError, and change the TResult default from the bare MutationState to a
parameterized MutationState<TData, TError, TVariables, TContext> across the
three declarations mentioned (MutationStateOptions, getResult, and
useMutationState) so that provided TData/TError/TVariables/TContext flow into
the result type and improve inference for mutation.state.error in select
callbacks.

@TkDodo
Copy link
Copy Markdown
Collaborator

TkDodo commented Apr 13, 2026

after

const result = useMutationState({
select: (mutation) => mutation.state.data
})
// result: number[]

not true. it’s still unknown[] because there is now way to infer from. Also, there’s still a type-error in your implementation. I don’t think this is possible or desirable.

@TkDodo TkDodo closed this Apr 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants