Skip to content

Commit

Permalink
Merge pull request #1965 from reduxjs/draft/amazing-rosalind
Browse files Browse the repository at this point in the history
  • Loading branch information
markerikson authored Nov 4, 2022
2 parents ad40b97 + bafe55e commit 5082af7
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 7 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: 14.x
node-version: 16.x
cache: 'yarn'

- name: Install dependencies
Expand All @@ -39,8 +39,8 @@ jobs:
strategy:
fail-fast: false
matrix:
node: ['14.x']
ts: ['4.0', '4.1', '4.2', '4.3', '4.4', '4.5', '4.6', 'next']
node: ['16.x']
ts: ['4.1', '4.2', '4.3', '4.4', '4.5', '4.6', '4.7', '4.8', '4.9.2-rc']
steps:
- name: Checkout repo
uses: actions/checkout@v2
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/useSelector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useContext, useDebugValue } from 'react'

import { useReduxContext as useDefaultReduxContext } from './useReduxContext'
import { ReactReduxContext } from '../components/Context'
import type { EqualityFn } from '../types'
import type { EqualityFn, NoInfer } from '../types'
import type { uSESWS } from '../utils/useSyncExternalStore'
import { notInitialized } from '../utils/useSyncExternalStore'

Expand Down Expand Up @@ -32,7 +32,7 @@ export function createSelectorHook(

return function useSelector<TState, Selected extends unknown>(
selector: (state: TState) => Selected,
equalityFn: EqualityFn<Selected> = refEquality
equalityFn: EqualityFn<NoInfer<Selected>> = refEquality
): Selected {
if (process.env.NODE_ENV !== 'production') {
if (!selector) {
Expand Down
4 changes: 3 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ export type ResolveThunks<TDispatchProps> = TDispatchProps extends {
export interface TypedUseSelectorHook<TState> {
<TSelected>(
selector: (state: TState) => TSelected,
equalityFn?: EqualityFn<TSelected>
equalityFn?: EqualityFn<NoInfer<TSelected>>
): TSelected
}

export type NoInfer<T> = [T][T extends any ? 0 : never]
16 changes: 15 additions & 1 deletion test/typetests/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import {
fetchCount,
} from './counterApp'

import { expectType } from '../typeTestHelpers'
import { expectType, expectExactType } from '../typeTestHelpers'

function preTypedHooksSetup() {
// Standard hooks setup
Expand Down Expand Up @@ -87,6 +87,20 @@ function testShallowEqual() {
shallowEqual({ test: 'test' }, { test: 'test' })
shallowEqual({ test: 'test' }, 'a')
const x: boolean = shallowEqual('a', 'a')

type TestState = { stateProp: string }

// Additionally, it should infer its type from arguments and not become `any`
const selected1 = useSelector(
(state: TestState) => state.stateProp,
shallowEqual
)
expectExactType<string>(selected1)

const useAppSelector: TypedUseSelectorHook<TestState> = useSelector

const selected2 = useAppSelector((state) => state.stateProp, shallowEqual)
expectExactType<string>(selected2)
}

function testUseDispatch() {
Expand Down

0 comments on commit 5082af7

Please sign in to comment.