Skip to content

Commit 1659df0

Browse files
authored
Merge pull request #1887 from reduxjs/feature/v8-types-updates
2 parents f965039 + 857311d commit 1659df0

12 files changed

+83
-139
lines changed

package.json

+7-5
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
"react": "^18.0.0"
4444
},
4545
"peerDependenciesMeta": {
46+
"@types/react": {
47+
"optional": true
48+
},
4649
"react-dom": {
4750
"optional": true
4851
},
@@ -81,11 +84,10 @@
8184
"@testing-library/react-hooks": "^3.4.2",
8285
"@testing-library/react-native": "^7.1.0",
8386
"@types/object-assign": "^4.0.30",
84-
"@types/react": "^17.0.43",
85-
"@types/react-dom": "^17.0.14",
86-
"@types/react-is": "^17.0.3",
87-
"@types/react-native": "^0.64.12",
88-
"@types/react-redux": "^7.1.18",
87+
"@types/react": "^18",
88+
"@types/react-dom": "^18",
89+
"@types/react-is": "^17",
90+
"@types/react-native": "^0.67.4",
8991
"@typescript-eslint/eslint-plugin": "^4.28.0",
9092
"@typescript-eslint/parser": "^4.28.0",
9193
"babel-eslint": "^10.1.0",

src/components/connect.tsx

+12-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import type { Store, Dispatch, Action, AnyAction } from 'redux'
88
import type {
99
AdvancedComponentDecorator,
1010
ConnectedComponent,
11-
DefaultRootState,
1211
InferableComponentEnhancer,
1312
InferableComponentEnhancerWithProps,
1413
ResolveThunks,
@@ -246,7 +245,7 @@ export type ConnectedProps<TConnector> =
246245
: never
247246

248247
export interface ConnectOptions<
249-
State = DefaultRootState,
248+
State = unknown,
250249
TStateProps = {},
251250
TOwnProps = {},
252251
TMergedProps = {}
@@ -289,7 +288,7 @@ export interface ConnectOptions<
289288
* @param mergeProps
290289
* @param options
291290
*/
292-
export interface Connect<DefaultState = DefaultRootState> {
291+
export interface Connect<DefaultState = unknown> {
293292
// tslint:disable:no-unnecessary-generics
294293
(): InferableComponentEnhancer<DispatchProp>
295294

@@ -453,7 +452,7 @@ function connect<
453452
TDispatchProps = {},
454453
TOwnProps = {},
455454
TMergedProps = {},
456-
State = DefaultRootState
455+
State = unknown
457456
>(
458457
mapStateToProps?: MapStateToPropsParam<TStateProps, TOwnProps, State>,
459458
mapDispatchToProps?: MapDispatchToPropsParam<TDispatchProps, TOwnProps>,
@@ -527,12 +526,20 @@ function connect<
527526

528527
const displayName = `Connect(${wrappedComponentName})`
529528

530-
const selectorFactoryOptions: SelectorFactoryOptions<any, any, any, any> = {
529+
const selectorFactoryOptions: SelectorFactoryOptions<
530+
any,
531+
any,
532+
any,
533+
any,
534+
State
535+
> = {
531536
shouldHandleStateChanges,
532537
displayName,
533538
wrappedComponentName,
534539
WrappedComponent,
540+
// @ts-ignore
535541
initMapStateToProps,
542+
// @ts-ignore
536543
initMapDispatchToProps,
537544
// @ts-ignore
538545
initMergeProps,

src/connect/selectorFactory.ts

+11-23
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Dispatch, Action } from 'redux'
22
import verifySubselectors from './verifySubselectors'
3-
import type { DefaultRootState, EqualityFn } from '../types'
3+
import type { EqualityFn } from '../types'
44

55
export type SelectorFactory<S, TProps, TOwnProps, TFactoryOptions> = (
66
dispatch: Dispatch<Action>,
@@ -13,26 +13,17 @@ export type Selector<S, TProps, TOwnProps = null> = TOwnProps extends
1313
? (state: S) => TProps
1414
: (state: S, ownProps: TOwnProps) => TProps
1515

16-
export type MapStateToProps<
17-
TStateProps,
18-
TOwnProps,
19-
State = DefaultRootState
20-
> = (state: State, ownProps: TOwnProps) => TStateProps
16+
export type MapStateToProps<TStateProps, TOwnProps, State = unknown> = (
17+
state: State,
18+
ownProps: TOwnProps
19+
) => TStateProps
2120

22-
export type MapStateToPropsFactory<
23-
TStateProps,
24-
TOwnProps,
25-
State = DefaultRootState
26-
> = (
21+
export type MapStateToPropsFactory<TStateProps, TOwnProps, State = unknown> = (
2722
initialState: State,
2823
ownProps: TOwnProps
2924
) => MapStateToProps<TStateProps, TOwnProps, State>
3025

31-
export type MapStateToPropsParam<
32-
TStateProps,
33-
TOwnProps,
34-
State = DefaultRootState
35-
> =
26+
export type MapStateToPropsParam<TStateProps, TOwnProps, State = unknown> =
3627
| MapStateToPropsFactory<TStateProps, TOwnProps, State>
3728
| MapStateToProps<TStateProps, TOwnProps, State>
3829
| null
@@ -66,10 +57,7 @@ export type MergeProps<TStateProps, TDispatchProps, TOwnProps, TMergedProps> = (
6657
ownProps: TOwnProps
6758
) => TMergedProps
6859

69-
interface PureSelectorFactoryComparisonOptions<
70-
TOwnProps,
71-
State = DefaultRootState
72-
> {
60+
interface PureSelectorFactoryComparisonOptions<TOwnProps, State = unknown> {
7361
areStatesEqual: EqualityFn<State>
7462
areOwnPropsEqual: EqualityFn<TOwnProps>
7563
areStatePropsEqual: EqualityFn<unknown>
@@ -81,7 +69,7 @@ export function pureFinalPropsSelectorFactory<
8169
TOwnProps,
8270
TDispatchProps,
8371
TMergedProps,
84-
State = DefaultRootState
72+
State = unknown
8573
>(
8674
mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps, State> & {
8775
dependsOnOwnProps: boolean
@@ -180,7 +168,7 @@ export interface SelectorFactoryOptions<
180168
TOwnProps,
181169
TDispatchProps,
182170
TMergedProps,
183-
State = DefaultRootState
171+
State = unknown
184172
> extends PureSelectorFactoryComparisonOptions<TOwnProps, State> {
185173
initMapStateToProps: (
186174
dispatch: Dispatch,
@@ -207,7 +195,7 @@ export default function finalPropsSelectorFactory<
207195
TOwnProps,
208196
TDispatchProps,
209197
TMergedProps,
210-
State = DefaultRootState
198+
State = unknown
211199
>(
212200
dispatch: Dispatch<Action>,
213201
{

src/connect/wrapMapToProps.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { FixTypeLater } from '../types'
44
import verifyPlainObject from '../utils/verifyPlainObject'
55

66
type AnyState = { [key: string]: any }
7-
type StateOrDispatch<S = AnyState> = S | Dispatch
7+
type StateOrDispatch<S extends AnyState = AnyState> = S | Dispatch
88

99
type AnyProps = { [key: string]: any }
1010

src/hooks/useDispatch.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
ReactReduxContextValue,
77
} from '../components/Context'
88
import { useStore as useDefaultStore, createStoreHook } from './useStore'
9-
import { RootStateOrAny } from '../types'
109

1110
/**
1211
* Hook factory, which creates a `useDispatch` hook bound to a given context.
@@ -15,7 +14,7 @@ import { RootStateOrAny } from '../types'
1514
* @returns {Function} A `useDispatch` hook bound to the specified context.
1615
*/
1716
export function createDispatchHook<
18-
S = RootStateOrAny,
17+
S = unknown,
1918
A extends Action = AnyAction
2019
// @ts-ignore
2120
>(context?: Context<ReactReduxContextValue<S, A>> = ReactReduxContext) {

src/hooks/useSelector.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useContext, useDebugValue } from 'react'
22

33
import { useReduxContext as useDefaultReduxContext } from './useReduxContext'
44
import { ReactReduxContext } from '../components/Context'
5-
import type { DefaultRootState, EqualityFn } from '../types'
5+
import type { EqualityFn } from '../types'
66
import type { uSESWS } from '../utils/useSyncExternalStore'
77
import { notInitialized } from '../utils/useSyncExternalStore'
88

@@ -21,7 +21,7 @@ const refEquality: EqualityFn<any> = (a, b) => a === b
2121
*/
2222
export function createSelectorHook(
2323
context = ReactReduxContext
24-
): <TState = DefaultRootState, Selected = unknown>(
24+
): <TState = unknown, Selected = unknown>(
2525
selector: (state: TState) => Selected,
2626
equalityFn?: EqualityFn<Selected>
2727
) => Selected {

src/hooks/useStore.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
ReactReduxContextValue,
66
} from '../components/Context'
77
import { useReduxContext as useDefaultReduxContext } from './useReduxContext'
8-
import { RootStateOrAny } from '../types'
98

109
/**
1110
* Hook factory, which creates a `useStore` hook bound to a given context.
@@ -14,7 +13,7 @@ import { RootStateOrAny } from '../types'
1413
* @returns {Function} A `useStore` hook bound to the specified context.
1514
*/
1615
export function createStoreHook<
17-
S = RootStateOrAny,
16+
S = unknown,
1817
A extends BasicAction = AnyAction
1918
// @ts-ignore
2019
>(context?: Context<ReactReduxContextValue<S, A>> = ReactReduxContext) {

src/types.ts

-10
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,7 @@ export type FixTypeLater = any
1010

1111
export type EqualityFn<T> = (a: T, b: T) => boolean
1212

13-
/**
14-
* This interface can be augmented by users to add default types for the root state when
15-
* using `react-redux`.
16-
* Use module augmentation to append your own type definition in a your_custom_type.d.ts file.
17-
* https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
18-
*/
19-
// tslint:disable-next-line:no-empty-interface
20-
export interface DefaultRootState {}
21-
2213
export type AnyIfEmpty<T extends object> = keyof T extends never ? any : T
23-
export type RootStateOrAny = AnyIfEmpty<DefaultRootState>
2414

2515
export type DistributiveOmit<T, K extends keyof T> = T extends unknown
2616
? Omit<T, K>

test/components/connect.spec.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -2018,6 +2018,7 @@ describe('React', () => {
20182018
return false
20192019
}
20202020
render() {
2021+
// @ts-ignore don't care about "children" errors
20212022
return this.props.children
20222023
}
20232024
}

test/typetests/connect-options-and-issues.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import {
3131
createSelectorHook,
3232
createStoreHook,
3333
TypedUseSelectorHook,
34-
DefaultRootState,
3534
} from '../../src/index'
3635

3736
import { expectType } from '../typeTestHelpers'
@@ -837,7 +836,7 @@ function testRef() {
837836
function testConnectDefaultState() {
838837
connect((state) => {
839838
const s = state
840-
expectType<DefaultRootState>(s)
839+
expectType<unknown>(s)
841840
return state
842841
})
843842

test/typetests/hooks.tsx

+23-19
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import * as React from 'react'
44
import * as ReactDOM from 'react-dom'
5-
import { Store, Dispatch, configureStore } from '@reduxjs/toolkit'
5+
import { Store, Dispatch, configureStore, AnyAction } from '@reduxjs/toolkit'
66
import {
77
connect,
88
ConnectedProps,
@@ -34,6 +34,8 @@ import {
3434
fetchCount,
3535
} from './counterApp'
3636

37+
import { expectType } from '../typeTestHelpers'
38+
3739
function preTypedHooksSetup() {
3840
// Standard hooks setup
3941
const useAppDispatch = () => useDispatch<AppDispatch>()
@@ -147,8 +149,7 @@ function testUseSelector() {
147149
useSelector(selector, 'a')
148150
useSelector(selector, (l, r) => l === r)
149151
useSelector(selector, (l, r) => {
150-
// $ExpectType { counter: number; active: string; }
151-
l
152+
expectType<{ counter: number; active: string }>(l)
152153
return l === r
153154
})
154155

@@ -169,12 +170,11 @@ function testUseSelector() {
169170

170171
const useTypedSelector: TypedUseSelectorHook<RootState> = useSelector
171172

172-
// $ExpectType string
173173
const r = useTypedSelector((state) => {
174-
// $ExpectType RootState
175-
state
174+
expectType<RootState>(state)
176175
return state.property
177176
})
177+
expectType<string>(r)
178178
}
179179

180180
function testUseStore() {
@@ -188,7 +188,7 @@ function testUseStore() {
188188

189189
const untypedStore = useStore()
190190
const state = untypedStore.getState()
191-
state.things.stuff.anything // any by default
191+
expectType<unknown>(state)
192192

193193
const typedStore = useStore<TypedState, TypedAction>()
194194
const typedState = typedStore.getState()
@@ -211,18 +211,22 @@ function testCreateHookFunctions() {
211211
>(null as any)
212212

213213
// No context tests
214-
// $ExpectType () => Dispatch<AnyAction>
215-
createDispatchHook()
216-
// $ExpectType <Selected extends unknown>(selector: (state: any) => Selected, equalityFn?: ((previous: Selected, next: Selected) => boolean) | undefined) => Selected
217-
createSelectorHook()
218-
// $ExpectType () => Store<any, AnyAction>
219-
createStoreHook()
214+
expectType<() => Dispatch<AnyAction>>(createDispatchHook())
215+
expectType<
216+
<Selected extends unknown>(
217+
selector: (state: any) => Selected,
218+
equalityFn?: ((previous: Selected, next: Selected) => boolean) | undefined
219+
) => Selected
220+
>(createSelectorHook())
221+
expectType<() => Store<any, AnyAction>>(createStoreHook())
220222

221223
// With context tests
222-
// $ExpectType () => Dispatch<RootAction>
223-
createDispatchHook(Context)
224-
// $ExpectType <Selected extends unknown>(selector: (state: RootState) => Selected, equalityFn?: ((previous: Selected, next: Selected) => boolean) | undefined) => Selected
225-
createSelectorHook(Context)
226-
// $ExpectType () => Store<RootState, RootAction>
227-
createStoreHook(Context)
224+
expectType<() => Dispatch<RootAction>>(createDispatchHook(Context))
225+
expectType<
226+
<Selected extends unknown>(
227+
selector: (state: RootState) => Selected,
228+
equalityFn?: ((previous: Selected, next: Selected) => boolean) | undefined
229+
) => Selected
230+
>(createSelectorHook(Context))
231+
expectType<() => Store<RootState, RootAction>>(createStoreHook(Context))
228232
}

0 commit comments

Comments
 (0)