TypedUseSelectorHook infers `any` with `shallowEqual` since 9.3.1 (NoInfer dropped)
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 72/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript
- Domain
- testing-qa
Research direction
Start with src/types.ts, where TypedUseSelectorHook defines the equalityFn parameter, and compare its NoInfer usage with the UseSelector overloads. Add a type test for shallowEqual with strictFunctionTypes disabled, as described in the issue. Done when the test confirms the selector return type is preserved and the regression is covered.
Written by the indexing model from the issue text.
Description
Heads-up: this was investigated and drafted with the help of a coding agent, sorry about that in advance. We checked the repro and cause by hand against the published 9.3.0 / 9.3.1 packages, and it looks like a real regression, so we wanted to report it.
What version of React, ReactDOM/React Native, Redux, and React Redux are you using?
- React: 19.2.6
- ReactDOM: 19.2.6
- Redux: 5.0.1
- React Redux: 9.3.1 (also 9.4.0-alpha.2). TypeScript 5.9.3
What is the current behavior?
With strictFunctionTypes off (for example "strict": false), a TypedUseSelectorHook called with shallowEqual now infers its result as any. In 9.3.0 it inferred the selector's return type.
import { shallowEqual, type TypedUseSelectorHook, useSelector } from 'react-redux'
type RootState = { plans: Record<string, { key: string }> }
const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
const result = useAppSelector(s => ({ plans: s.plans }), shallowEqual)
const probe: number = result
// 9.3.0: error, result is { plans: Record<string, { key: string }> }
// 9.3.1: no error, result is any
tsc --noEmit --strict --strictFunctionTypes false repro.ts
In our app this silently turned ~200 selectors into any. We only noticed because a few Object.values(...) calls became unknown[].
Cause: 520b2001f4 (removing the custom NoInfer helper, #2313) dropped the wrapper from TypedUseSelectorHook instead of switching to the native NoInfer:
// src/types.ts
- equalityFn?: EqualityFn<NoInfer<TSelected>>,
+ equalityFn?: EqualityFn<TSelected>,
With bivariant parameter checking, shallowEqual(objA: any, objB: any) becomes an inference candidate for TSelected, and any wins. This is the same symptom as #2186 / #1964.
What is the expected behavior?
TypedUseSelectorHook keeps inferring the selector's return type, by using the native NoInfer: equalityFn?: EqualityFn<NoInfer<TSelected>>. A type test for shallowEqual with strictFunctionTypes: false would catch it next time.
Side note: useSelector.withTypes<RootState>() and a plain useSelector((s: RootState) => ..., shallowEqual) infer any under the same setting on 9.3.0 too, because the UseSelector interface overloads don't use NoInfer. So that part isn't a regression, but the same fix would cover it.
Which browser and OS are affected by this issue?
None, it's types only.
Did this work in previous versions of React Redux?
- Yes (9.3.0)
- Dominant language
- TypeScript
- Stars
- 23.4k
- Forks
- 3.3k
- PR merge metrics
- No merged PRs in 30d
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from reduxjs/react-redux
-
Breaking Change Tooling
Difficulty 5/5 Over a week Newbie friendliness 15/100
reduxjs/react-redux#2415 ·
-
feat!: remove `alternate-renderers` entry point for v10Possibly taken @aryaemami59 claimed this 135 days ago. OpenBreaking Change
reduxjs/react-redux#2336 · 1 reaction · 1 assignee ·
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
reduxjs/react-redux#2160 · 1 reaction ·
-
Performance
Difficulty 5/5 Over a week Newbie friendliness 25/100
reduxjs/react-redux#2086 · 16 comments · 2 reactions ·
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
reduxjs/react-redux#2060 · 2 comments · 1 reaction ·
All issues in reduxjs/react-redux
Similar issues
-
Autocomplete still accepts an option after becoming disabledPossibly taken @Xapollon430 claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 67/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Difficulty 1/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
tashfeenahmed/freellmapi#1920 ·
Maintainers usually reply within 1 day