diff --git a/package.json b/package.json index 96b082316..c41b6385c 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,9 @@ "react": "^18.0.0" }, "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, "react-dom": { "optional": true }, @@ -81,11 +84,10 @@ "@testing-library/react-hooks": "^3.4.2", "@testing-library/react-native": "^7.1.0", "@types/object-assign": "^4.0.30", - "@types/react": "^17.0.43", - "@types/react-dom": "^17.0.14", - "@types/react-is": "^17.0.3", - "@types/react-native": "^0.64.12", - "@types/react-redux": "^7.1.18", + "@types/react": "^18", + "@types/react-dom": "^18", + "@types/react-is": "^17", + "@types/react-native": "^0.67.4", "@typescript-eslint/eslint-plugin": "^4.28.0", "@typescript-eslint/parser": "^4.28.0", "babel-eslint": "^10.1.0", diff --git a/src/components/connect.tsx b/src/components/connect.tsx index eeb3356b4..9b21a3cae 100644 --- a/src/components/connect.tsx +++ b/src/components/connect.tsx @@ -8,7 +8,6 @@ import type { Store, Dispatch, Action, AnyAction } from 'redux' import type { AdvancedComponentDecorator, ConnectedComponent, - DefaultRootState, InferableComponentEnhancer, InferableComponentEnhancerWithProps, ResolveThunks, @@ -246,7 +245,7 @@ export type ConnectedProps = : never export interface ConnectOptions< - State = DefaultRootState, + State = unknown, TStateProps = {}, TOwnProps = {}, TMergedProps = {} @@ -289,7 +288,7 @@ export interface ConnectOptions< * @param mergeProps * @param options */ -export interface Connect { +export interface Connect { // tslint:disable:no-unnecessary-generics (): InferableComponentEnhancer @@ -453,7 +452,7 @@ function connect< TDispatchProps = {}, TOwnProps = {}, TMergedProps = {}, - State = DefaultRootState + State = unknown >( mapStateToProps?: MapStateToPropsParam, mapDispatchToProps?: MapDispatchToPropsParam, @@ -527,12 +526,20 @@ function connect< const displayName = `Connect(${wrappedComponentName})` - const selectorFactoryOptions: SelectorFactoryOptions = { + const selectorFactoryOptions: SelectorFactoryOptions< + any, + any, + any, + any, + State + > = { shouldHandleStateChanges, displayName, wrappedComponentName, WrappedComponent, + // @ts-ignore initMapStateToProps, + // @ts-ignore initMapDispatchToProps, // @ts-ignore initMergeProps, diff --git a/src/connect/selectorFactory.ts b/src/connect/selectorFactory.ts index 5321ac517..8f3c4b73d 100644 --- a/src/connect/selectorFactory.ts +++ b/src/connect/selectorFactory.ts @@ -1,6 +1,6 @@ import type { Dispatch, Action } from 'redux' import verifySubselectors from './verifySubselectors' -import type { DefaultRootState, EqualityFn } from '../types' +import type { EqualityFn } from '../types' export type SelectorFactory = ( dispatch: Dispatch, @@ -13,26 +13,17 @@ export type Selector = TOwnProps extends ? (state: S) => TProps : (state: S, ownProps: TOwnProps) => TProps -export type MapStateToProps< - TStateProps, - TOwnProps, - State = DefaultRootState -> = (state: State, ownProps: TOwnProps) => TStateProps +export type MapStateToProps = ( + state: State, + ownProps: TOwnProps +) => TStateProps -export type MapStateToPropsFactory< - TStateProps, - TOwnProps, - State = DefaultRootState -> = ( +export type MapStateToPropsFactory = ( initialState: State, ownProps: TOwnProps ) => MapStateToProps -export type MapStateToPropsParam< - TStateProps, - TOwnProps, - State = DefaultRootState -> = +export type MapStateToPropsParam = | MapStateToPropsFactory | MapStateToProps | null @@ -66,10 +57,7 @@ export type MergeProps = ( ownProps: TOwnProps ) => TMergedProps -interface PureSelectorFactoryComparisonOptions< - TOwnProps, - State = DefaultRootState -> { +interface PureSelectorFactoryComparisonOptions { areStatesEqual: EqualityFn areOwnPropsEqual: EqualityFn areStatePropsEqual: EqualityFn @@ -81,7 +69,7 @@ export function pureFinalPropsSelectorFactory< TOwnProps, TDispatchProps, TMergedProps, - State = DefaultRootState + State = unknown >( mapStateToProps: MapStateToPropsParam & { dependsOnOwnProps: boolean @@ -180,7 +168,7 @@ export interface SelectorFactoryOptions< TOwnProps, TDispatchProps, TMergedProps, - State = DefaultRootState + State = unknown > extends PureSelectorFactoryComparisonOptions { initMapStateToProps: ( dispatch: Dispatch, @@ -207,7 +195,7 @@ export default function finalPropsSelectorFactory< TOwnProps, TDispatchProps, TMergedProps, - State = DefaultRootState + State = unknown >( dispatch: Dispatch, { diff --git a/src/connect/wrapMapToProps.ts b/src/connect/wrapMapToProps.ts index 9671abdc4..5b8387368 100644 --- a/src/connect/wrapMapToProps.ts +++ b/src/connect/wrapMapToProps.ts @@ -4,7 +4,7 @@ import { FixTypeLater } from '../types' import verifyPlainObject from '../utils/verifyPlainObject' type AnyState = { [key: string]: any } -type StateOrDispatch = S | Dispatch +type StateOrDispatch = S | Dispatch type AnyProps = { [key: string]: any } diff --git a/src/hooks/useDispatch.ts b/src/hooks/useDispatch.ts index c84f1846e..ef22881bb 100644 --- a/src/hooks/useDispatch.ts +++ b/src/hooks/useDispatch.ts @@ -6,7 +6,6 @@ import { ReactReduxContextValue, } from '../components/Context' import { useStore as useDefaultStore, createStoreHook } from './useStore' -import { RootStateOrAny } from '../types' /** * Hook factory, which creates a `useDispatch` hook bound to a given context. @@ -15,7 +14,7 @@ import { RootStateOrAny } from '../types' * @returns {Function} A `useDispatch` hook bound to the specified context. */ export function createDispatchHook< - S = RootStateOrAny, + S = unknown, A extends Action = AnyAction // @ts-ignore >(context?: Context> = ReactReduxContext) { diff --git a/src/hooks/useSelector.ts b/src/hooks/useSelector.ts index f5b19c5b8..034b2d216 100644 --- a/src/hooks/useSelector.ts +++ b/src/hooks/useSelector.ts @@ -2,7 +2,7 @@ import { useContext, useDebugValue } from 'react' import { useReduxContext as useDefaultReduxContext } from './useReduxContext' import { ReactReduxContext } from '../components/Context' -import type { DefaultRootState, EqualityFn } from '../types' +import type { EqualityFn } from '../types' import type { uSESWS } from '../utils/useSyncExternalStore' import { notInitialized } from '../utils/useSyncExternalStore' @@ -21,7 +21,7 @@ const refEquality: EqualityFn = (a, b) => a === b */ export function createSelectorHook( context = ReactReduxContext -): ( +): ( selector: (state: TState) => Selected, equalityFn?: EqualityFn ) => Selected { diff --git a/src/hooks/useStore.ts b/src/hooks/useStore.ts index e1cfb9be0..c1dca43cb 100644 --- a/src/hooks/useStore.ts +++ b/src/hooks/useStore.ts @@ -5,7 +5,6 @@ import { ReactReduxContextValue, } from '../components/Context' import { useReduxContext as useDefaultReduxContext } from './useReduxContext' -import { RootStateOrAny } from '../types' /** * Hook factory, which creates a `useStore` hook bound to a given context. @@ -14,7 +13,7 @@ import { RootStateOrAny } from '../types' * @returns {Function} A `useStore` hook bound to the specified context. */ export function createStoreHook< - S = RootStateOrAny, + S = unknown, A extends BasicAction = AnyAction // @ts-ignore >(context?: Context> = ReactReduxContext) { diff --git a/src/types.ts b/src/types.ts index 23c31801e..599a568a3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -10,17 +10,7 @@ export type FixTypeLater = any export type EqualityFn = (a: T, b: T) => boolean -/** - * This interface can be augmented by users to add default types for the root state when - * using `react-redux`. - * Use module augmentation to append your own type definition in a your_custom_type.d.ts file. - * https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation - */ -// tslint:disable-next-line:no-empty-interface -export interface DefaultRootState {} - export type AnyIfEmpty = keyof T extends never ? any : T -export type RootStateOrAny = AnyIfEmpty export type DistributiveOmit = T extends unknown ? Omit diff --git a/test/components/connect.spec.tsx b/test/components/connect.spec.tsx index beb4da5f6..e50c80ae6 100644 --- a/test/components/connect.spec.tsx +++ b/test/components/connect.spec.tsx @@ -2018,6 +2018,7 @@ describe('React', () => { return false } render() { + // @ts-ignore don't care about "children" errors return this.props.children } } diff --git a/test/typetests/connect-options-and-issues.tsx b/test/typetests/connect-options-and-issues.tsx index 7cb319070..24e3f4b92 100644 --- a/test/typetests/connect-options-and-issues.tsx +++ b/test/typetests/connect-options-and-issues.tsx @@ -31,7 +31,6 @@ import { createSelectorHook, createStoreHook, TypedUseSelectorHook, - DefaultRootState, } from '../../src/index' import { expectType } from '../typeTestHelpers' @@ -837,7 +836,7 @@ function testRef() { function testConnectDefaultState() { connect((state) => { const s = state - expectType(s) + expectType(s) return state }) diff --git a/test/typetests/hooks.tsx b/test/typetests/hooks.tsx index 0548c57aa..84475e961 100644 --- a/test/typetests/hooks.tsx +++ b/test/typetests/hooks.tsx @@ -2,7 +2,7 @@ import * as React from 'react' import * as ReactDOM from 'react-dom' -import { Store, Dispatch, configureStore } from '@reduxjs/toolkit' +import { Store, Dispatch, configureStore, AnyAction } from '@reduxjs/toolkit' import { connect, ConnectedProps, @@ -34,6 +34,8 @@ import { fetchCount, } from './counterApp' +import { expectType } from '../typeTestHelpers' + function preTypedHooksSetup() { // Standard hooks setup const useAppDispatch = () => useDispatch() @@ -147,8 +149,7 @@ function testUseSelector() { useSelector(selector, 'a') useSelector(selector, (l, r) => l === r) useSelector(selector, (l, r) => { - // $ExpectType { counter: number; active: string; } - l + expectType<{ counter: number; active: string }>(l) return l === r }) @@ -169,12 +170,11 @@ function testUseSelector() { const useTypedSelector: TypedUseSelectorHook = useSelector - // $ExpectType string const r = useTypedSelector((state) => { - // $ExpectType RootState - state + expectType(state) return state.property }) + expectType(r) } function testUseStore() { @@ -188,7 +188,7 @@ function testUseStore() { const untypedStore = useStore() const state = untypedStore.getState() - state.things.stuff.anything // any by default + expectType(state) const typedStore = useStore() const typedState = typedStore.getState() @@ -211,18 +211,22 @@ function testCreateHookFunctions() { >(null as any) // No context tests - // $ExpectType () => Dispatch - createDispatchHook() - // $ExpectType (selector: (state: any) => Selected, equalityFn?: ((previous: Selected, next: Selected) => boolean) | undefined) => Selected - createSelectorHook() - // $ExpectType () => Store - createStoreHook() + expectType<() => Dispatch>(createDispatchHook()) + expectType< + ( + selector: (state: any) => Selected, + equalityFn?: ((previous: Selected, next: Selected) => boolean) | undefined + ) => Selected + >(createSelectorHook()) + expectType<() => Store>(createStoreHook()) // With context tests - // $ExpectType () => Dispatch - createDispatchHook(Context) - // $ExpectType (selector: (state: RootState) => Selected, equalityFn?: ((previous: Selected, next: Selected) => boolean) | undefined) => Selected - createSelectorHook(Context) - // $ExpectType () => Store - createStoreHook(Context) + expectType<() => Dispatch>(createDispatchHook(Context)) + expectType< + ( + selector: (state: RootState) => Selected, + equalityFn?: ((previous: Selected, next: Selected) => boolean) | undefined + ) => Selected + >(createSelectorHook(Context)) + expectType<() => Store>(createStoreHook(Context)) } diff --git a/yarn.lock b/yarn.lock index 35977a1a8..dc2a5043a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2260,7 +2260,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/dom@npm:^8.0.0": +"@testing-library/dom@npm:^8.0.0, @testing-library/dom@npm:^8.5.0": version: 8.11.1 resolution: "@testing-library/dom@npm:8.11.1" dependencies: @@ -2276,22 +2276,6 @@ __metadata: languageName: node linkType: hard -"@testing-library/dom@npm:^8.5.0": - version: 8.10.1 - resolution: "@testing-library/dom@npm:8.10.1" - dependencies: - "@babel/code-frame": ^7.10.4 - "@babel/runtime": ^7.12.5 - "@types/aria-query": ^4.2.0 - aria-query: ^5.0.0 - chalk: ^4.1.0 - dom-accessibility-api: ^0.5.9 - lz-string: ^1.4.4 - pretty-format: ^27.0.2 - checksum: d37eef1a3db509f3be3fcb77721f04694aadba7de195c0338d7f203668e132452a694504733ecee6fc71838abca8c02d27e78545cd8d6e89abae95d4ab2c1ab0 - languageName: node - linkType: hard - "@testing-library/jest-dom@npm:^5.11.5": version: 5.14.1 resolution: "@testing-library/jest-dom@npm:5.14.1" @@ -2465,7 +2449,7 @@ __metadata: languageName: node linkType: hard -"@types/hoist-non-react-statics@npm:^3.3.0, @types/hoist-non-react-statics@npm:^3.3.1": +"@types/hoist-non-react-statics@npm:^3.3.1": version: 3.3.1 resolution: "@types/hoist-non-react-statics@npm:3.3.1" dependencies: @@ -2569,16 +2553,16 @@ __metadata: languageName: node linkType: hard -"@types/react-dom@npm:*, @types/react-dom@npm:^17.0.14": - version: 17.0.14 - resolution: "@types/react-dom@npm:17.0.14" +"@types/react-dom@npm:*, @types/react-dom@npm:^18": + version: 18.0.0 + resolution: "@types/react-dom@npm:18.0.0" dependencies: "@types/react": "*" - checksum: 3565d6658304b00acfe90504e5f52f744a46f1acab60a3c369d03be2f9a48ba7b2f163b212e4d9907e0452f574191ef618d30da0214a437ba30d2e66e969f0d1 + checksum: 5db55eace82432392820274f22f895ee7540444b1c53ec0830da9d3ba7cd37f77b20a23b1abb2d193b163430ee358b51dc8f08494cddb8bb77e6942324d0e95c languageName: node linkType: hard -"@types/react-is@npm:^17.0.3": +"@types/react-is@npm:^17": version: 17.0.3 resolution: "@types/react-is@npm:17.0.3" dependencies: @@ -2587,24 +2571,12 @@ __metadata: languageName: node linkType: hard -"@types/react-native@npm:^0.64.12": - version: 0.64.12 - resolution: "@types/react-native@npm:0.64.12" - dependencies: - "@types/react": "*" - checksum: de9dd20a86d02b1e8715c55ec019c3062e9f1e52e4b09e4fb00f9ecd017b684c607871fc700722abfeca9b69820703871527db43170758a1984702192c34013a - languageName: node - linkType: hard - -"@types/react-redux@npm:^7.1.18": - version: 7.1.18 - resolution: "@types/react-redux@npm:7.1.18" +"@types/react-native@npm:^0.67.4": + version: 0.67.4 + resolution: "@types/react-native@npm:0.67.4" dependencies: - "@types/hoist-non-react-statics": ^3.3.0 "@types/react": "*" - hoist-non-react-statics: ^3.3.0 - redux: ^4.0.0 - checksum: b247ff7ce31cede226f4606571bf975aeec91fe911e65e72cecaaac7234d4d694a7be0791419bb4259c7012b662a96267f694daaacbc18f3157fc7f955af55c9 + checksum: 6d200dbdebe720203b73cdbd942c7f7fdb74cbfb816810875a7802eebad1a10b829fa2f8b6df6d152a979a6082a9461f08494a884db53629aae80f22e43ed0c7 languageName: node linkType: hard @@ -2617,25 +2589,14 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:*": - version: 17.0.35 - resolution: "@types/react@npm:17.0.35" +"@types/react@npm:*, @types/react@npm:^18": + version: 18.0.1 + resolution: "@types/react@npm:18.0.1" dependencies: "@types/prop-types": "*" "@types/scheduler": "*" csstype: ^3.0.2 - checksum: 8606c027a284555ee16097133156964e8b9373612e9979d8a6b02e9ce545b72809ad15b381664f2175b4afb2264bbb04254b0f91c8d16b3482b6f17a3123916f - languageName: node - linkType: hard - -"@types/react@npm:^17.0.43": - version: 17.0.43 - resolution: "@types/react@npm:17.0.43" - dependencies: - "@types/prop-types": "*" - "@types/scheduler": "*" - csstype: ^3.0.2 - checksum: d368aa3d03f1951554398882771d562a0e0c81fe02f7d11d974721bbb667d2643b95ecdc01c783bdab2c2f69704524379f96e73e86b413faf3501c932c25b4b6 + checksum: 12cf4f38f8e58f12700a60579b0b54719d632181cb6efe8574aac2314c6826f1058091a388512e8b98d818511aee6d808c2818e964d28a6fe491d0cf2d98866a languageName: node linkType: hard @@ -4458,14 +4419,7 @@ __metadata: languageName: node linkType: hard -"dom-accessibility-api@npm:^0.5.6": - version: 0.5.6 - resolution: "dom-accessibility-api@npm:0.5.6" - checksum: b579681083e683291df022bdf094dae2c7e39db0ff28f70ed2c8368eda203fe4c45bcf92f1c623ce4b746cb245f9a5dc9d176f1781d600b9218728d3a1d1580f - languageName: node - linkType: hard - -"dom-accessibility-api@npm:^0.5.9": +"dom-accessibility-api@npm:^0.5.6, dom-accessibility-api@npm:^0.5.9": version: 0.5.10 resolution: "dom-accessibility-api@npm:0.5.10" checksum: f6135bf1fe84b2eee884db115ad165e773811ed035dffb519750c137bf954d3f6c69d2f9e27510265303dc3c6050c775d2fc261e802ad7196154f4148312f653 @@ -8941,11 +8895,10 @@ __metadata: "@testing-library/react-native": ^7.1.0 "@types/hoist-non-react-statics": ^3.3.1 "@types/object-assign": ^4.0.30 - "@types/react": ^17.0.43 - "@types/react-dom": ^17.0.14 - "@types/react-is": ^17.0.3 - "@types/react-native": ^0.64.12 - "@types/react-redux": ^7.1.18 + "@types/react": ^18 + "@types/react-dom": ^18 + "@types/react-is": ^17 + "@types/react-native": ^0.67.4 "@types/use-sync-external-store": ^0.0.3 "@typescript-eslint/eslint-plugin": ^4.28.0 "@typescript-eslint/parser": ^4.28.0 @@ -8980,6 +8933,8 @@ __metadata: peerDependencies: react: ^18.0.0 peerDependenciesMeta: + "@types/react": + optional: true react-dom: optional: true react-native: @@ -9169,7 +9124,7 @@ __metadata: languageName: node linkType: hard -"redux@npm:^4.0.0, redux@npm:^4.0.5, redux@npm:^4.1.0": +"redux@npm:^4.0.5, redux@npm:^4.1.0": version: 4.1.1 resolution: "redux@npm:4.1.1" dependencies: