From 19cc9e45836e42b7b20386f8a9d47601676ceb14 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Sun, 10 Apr 2022 23:47:07 -0400 Subject: [PATCH] Remove ts-ignore for initMergeProps --- src/components/connect.tsx | 56 +++++-------------------------- src/connect/invalidArgFactory.ts | 14 ++++++++ src/connect/mapDispatchToProps.ts | 45 ++++++++++--------------- src/connect/mapStateToProps.ts | 27 +++++++-------- src/connect/mergeProps.ts | 56 +++++++++++++------------------ src/connect/selectorFactory.ts | 37 ++++++++++++-------- 6 files changed, 98 insertions(+), 137 deletions(-) create mode 100644 src/connect/invalidArgFactory.ts diff --git a/src/components/connect.tsx b/src/components/connect.tsx index 9b21a3cae..d97da5c7f 100644 --- a/src/components/connect.tsx +++ b/src/components/connect.tsx @@ -1,9 +1,9 @@ /* eslint-disable valid-jsdoc, @typescript-eslint/no-unused-vars */ import hoistStatics from 'hoist-non-react-statics' -import React, { useContext, useMemo, useRef, useReducer } from 'react' +import React, { useContext, useMemo, useRef } from 'react' import { isValidElementType, isContextConsumer } from 'react-is' -import type { Store, Dispatch, Action, AnyAction } from 'redux' +import type { Store } from 'redux' import type { AdvancedComponentDecorator, @@ -21,15 +21,12 @@ import defaultSelectorFactory, { MapDispatchToPropsNonObject, SelectorFactoryOptions, } from '../connect/selectorFactory' -import defaultMapDispatchToPropsFactories from '../connect/mapDispatchToProps' -import defaultMapStateToPropsFactories from '../connect/mapStateToProps' -import defaultMergePropsFactories from '../connect/mergeProps' +import { mapDispatchToPropsFactory } from '../connect/mapDispatchToProps' +import { mapStateToPropsFactory } from '../connect/mapStateToProps' +import { mergePropsFactory } from '../connect/mergeProps' import { createSubscription, Subscription } from '../utils/Subscription' -import { - useIsomorphicLayoutEffect, - canUseDOM, -} from '../utils/useIsomorphicLayoutEffect' +import { useIsomorphicLayoutEffect } from '../utils/useIsomorphicLayoutEffect' import shallowEqual from '../utils/shallowEqual' import { @@ -206,25 +203,6 @@ interface InternalConnectProps extends ConnectProps { reactReduxForwardedRef?: React.ForwardedRef } -function match( - arg: unknown, - factories: ((value: unknown) => T)[], - name: string -): T { - for (let i = factories.length - 1; i >= 0; i--) { - const result = factories[i](arg) - if (result) return result - } - - return ((dispatch: Dispatch, options: { wrappedComponentName: string }) => { - throw new Error( - `Invalid value of type ${typeof arg} for ${name} argument when connecting component ${ - options.wrappedComponentName - }.` - ) - }) as any -} - function strictEqual(a: unknown, b: unknown) { return a === b } @@ -485,24 +463,9 @@ function connect< type WrappedComponentProps = TOwnProps & ConnectProps - const initMapStateToProps = match( - mapStateToProps, - // @ts-ignore - defaultMapStateToPropsFactories, - 'mapStateToProps' - )! - const initMapDispatchToProps = match( - mapDispatchToProps, - // @ts-ignore - defaultMapDispatchToPropsFactories, - 'mapDispatchToProps' - )! - const initMergeProps = match( - mergeProps, - // @ts-ignore - defaultMergePropsFactories, - 'mergeProps' - )! + const initMapStateToProps = mapStateToPropsFactory(mapStateToProps) + const initMapDispatchToProps = mapDispatchToPropsFactory(mapDispatchToProps) + const initMergeProps = mergePropsFactory(mergeProps) const shouldHandleStateChanges = Boolean(mapStateToProps) @@ -541,7 +504,6 @@ function connect< initMapStateToProps, // @ts-ignore initMapDispatchToProps, - // @ts-ignore initMergeProps, areStatesEqual, areStatePropsEqual, diff --git a/src/connect/invalidArgFactory.ts b/src/connect/invalidArgFactory.ts new file mode 100644 index 000000000..4129320a6 --- /dev/null +++ b/src/connect/invalidArgFactory.ts @@ -0,0 +1,14 @@ +import type { Action, Dispatch } from 'redux' + +export function createInvalidArgFactory(arg: unknown, name: string) { + return ( + dispatch: Dispatch>, + options: { readonly wrappedComponentName: string } + ) => { + throw new Error( + `Invalid value of type ${typeof arg} for ${name} argument when connecting component ${ + options.wrappedComponentName + }.` + ) + } +} diff --git a/src/connect/mapDispatchToProps.ts b/src/connect/mapDispatchToProps.ts index aee587812..48c5b0542 100644 --- a/src/connect/mapDispatchToProps.ts +++ b/src/connect/mapDispatchToProps.ts @@ -1,36 +1,25 @@ -import { ActionCreatorsMapObject, Dispatch } from 'redux' -import { FixTypeLater } from '../types' +import type { Action, Dispatch } from 'redux' import bindActionCreators from '../utils/bindActionCreators' import { wrapMapToPropsConstant, wrapMapToPropsFunc } from './wrapMapToProps' +import { createInvalidArgFactory } from './invalidArgFactory' +import type { MapDispatchToPropsParam } from './selectorFactory' -export function whenMapDispatchToPropsIsFunction( - mapDispatchToProps: ActionCreatorsMapObject | FixTypeLater -) { - return typeof mapDispatchToProps === 'function' - ? wrapMapToPropsFunc(mapDispatchToProps, 'mapDispatchToProps') - : undefined -} - -export function whenMapDispatchToPropsIsMissing(mapDispatchToProps: undefined) { - return !mapDispatchToProps - ? wrapMapToPropsConstant((dispatch: Dispatch) => ({ - dispatch, - })) - : undefined -} - -export function whenMapDispatchToPropsIsObject( - mapDispatchToProps: ActionCreatorsMapObject +export function mapDispatchToPropsFactory( + mapDispatchToProps: + | MapDispatchToPropsParam + | undefined ) { return mapDispatchToProps && typeof mapDispatchToProps === 'object' - ? wrapMapToPropsConstant((dispatch: Dispatch) => + ? wrapMapToPropsConstant((dispatch: Dispatch>) => + // @ts-ignore bindActionCreators(mapDispatchToProps, dispatch) ) - : undefined + : !mapDispatchToProps + ? wrapMapToPropsConstant((dispatch: Dispatch>) => ({ + dispatch, + })) + : typeof mapDispatchToProps === 'function' + ? // @ts-ignore + wrapMapToPropsFunc(mapDispatchToProps, 'mapDispatchToProps') + : createInvalidArgFactory(mapDispatchToProps, 'mapDispatchToProps') } - -export default [ - whenMapDispatchToPropsIsFunction, - whenMapDispatchToPropsIsMissing, - whenMapDispatchToPropsIsObject, -] diff --git a/src/connect/mapStateToProps.ts b/src/connect/mapStateToProps.ts index 2dcd7e7c3..fbf8a3ec2 100644 --- a/src/connect/mapStateToProps.ts +++ b/src/connect/mapStateToProps.ts @@ -1,17 +1,14 @@ -import { - MapToProps, - wrapMapToPropsConstant, - wrapMapToPropsFunc, -} from './wrapMapToProps' +import { wrapMapToPropsConstant, wrapMapToPropsFunc } from './wrapMapToProps' +import { createInvalidArgFactory } from './invalidArgFactory' +import type { MapStateToPropsParam } from './selectorFactory' -export function whenMapStateToPropsIsFunction(mapStateToProps?: MapToProps) { - return typeof mapStateToProps === 'function' - ? wrapMapToPropsFunc(mapStateToProps, 'mapStateToProps') - : undefined +export function mapStateToPropsFactory( + mapStateToProps: MapStateToPropsParam +) { + return !mapStateToProps + ? wrapMapToPropsConstant(() => ({})) + : typeof mapStateToProps === 'function' + ? // @ts-ignore + wrapMapToPropsFunc(mapStateToProps, 'mapStateToProps') + : createInvalidArgFactory(mapStateToProps, 'mapStateToProps') } - -export function whenMapStateToPropsIsMissing(mapStateToProps?: MapToProps) { - return !mapStateToProps ? wrapMapToPropsConstant(() => ({})) : undefined -} - -export default [whenMapStateToPropsIsFunction, whenMapStateToPropsIsMissing] diff --git a/src/connect/mergeProps.ts b/src/connect/mergeProps.ts index d94fdc369..c62027c4c 100644 --- a/src/connect/mergeProps.ts +++ b/src/connect/mergeProps.ts @@ -1,25 +1,23 @@ -import { Dispatch } from 'redux' +import type { Action, Dispatch } from 'redux' import verifyPlainObject from '../utils/verifyPlainObject' +import { createInvalidArgFactory } from './invalidArgFactory' +import type { MergeProps } from './selectorFactory' +import type { EqualityFn } from '../types' -type MergeProps = ( - stateProps: TStateProps, - dispatchProps: TDispatchProps, - ownProps: TOwnProps -) => TMergedProps - -export function defaultMergeProps( +export function defaultMergeProps< + TStateProps, + TDispatchProps, + TOwnProps, + TMergedProps +>( stateProps: TStateProps, dispatchProps: TDispatchProps, ownProps: TOwnProps -) { +): TMergedProps { + // @ts-ignore return { ...ownProps, ...stateProps, ...dispatchProps } } -interface InitMergeOptions { - displayName: string - areMergedPropsEqual: (a: any, b: any) => boolean -} - export function wrapMergePropsFunc< TStateProps, TDispatchProps, @@ -28,8 +26,11 @@ export function wrapMergePropsFunc< >( mergeProps: MergeProps ): ( - dispatch: Dispatch, - options: InitMergeOptions + dispatch: Dispatch>, + options: { + readonly displayName: string + readonly areMergedPropsEqual: EqualityFn + } ) => MergeProps { return function initMergePropsProxy( dispatch, @@ -61,20 +62,7 @@ export function wrapMergePropsFunc< } } -export function whenMergePropsIsFunction< - TStateProps, - TDispatchProps, - TOwnProps, - TMergedProps ->( - mergeProps: MergeProps -) { - return typeof mergeProps === 'function' - ? wrapMergePropsFunc(mergeProps) - : undefined -} - -export function whenMergePropsIsOmitted< +export function mergePropsFactory< TStateProps, TDispatchProps, TOwnProps, @@ -82,7 +70,9 @@ export function whenMergePropsIsOmitted< >( mergeProps?: MergeProps ) { - return !mergeProps ? () => defaultMergeProps : undefined + return !mergeProps + ? () => defaultMergeProps + : typeof mergeProps === 'function' + ? wrapMergePropsFunc(mergeProps) + : createInvalidArgFactory(mergeProps, 'mergeProps') } - -export default [whenMergePropsIsFunction, whenMergePropsIsOmitted] as const diff --git a/src/connect/selectorFactory.ts b/src/connect/selectorFactory.ts index fd5dea5f9..f0420a3f1 100644 --- a/src/connect/selectorFactory.ts +++ b/src/connect/selectorFactory.ts @@ -1,4 +1,5 @@ import type { Dispatch, Action } from 'redux' +import type { ComponentType } from 'react' import verifySubselectors from './verifySubselectors' import type { EqualityFn } from '../types' @@ -58,10 +59,9 @@ export type MergeProps = ( ) => TMergedProps interface PureSelectorFactoryComparisonOptions { - areStatesEqual: EqualityFn - areOwnPropsEqual: EqualityFn - areStatePropsEqual: EqualityFn - displayName: string + readonly areStatesEqual: EqualityFn + readonly areStatePropsEqual: EqualityFn + readonly areOwnPropsEqual: EqualityFn } export function pureFinalPropsSelectorFactory< @@ -162,24 +162,33 @@ interface WrappedMapDispatchToProps { readonly dependsOnOwnProps: boolean } +export interface InitOptions + extends PureSelectorFactoryComparisonOptions { + readonly shouldHandleStateChanges: boolean + readonly displayName: string + readonly wrappedComponentName: string + readonly WrappedComponent: ComponentType + readonly areMergedPropsEqual: EqualityFn +} + export interface SelectorFactoryOptions< TStateProps, TOwnProps, TDispatchProps, TMergedProps, State -> extends PureSelectorFactoryComparisonOptions { - initMapStateToProps: ( - dispatch: Dispatch, - options: PureSelectorFactoryComparisonOptions +> extends InitOptions { + readonly initMapStateToProps: ( + dispatch: Dispatch>, + options: InitOptions ) => WrappedMapStateToProps - initMapDispatchToProps: ( - dispatch: Dispatch, - options: PureSelectorFactoryComparisonOptions + readonly initMapDispatchToProps: ( + dispatch: Dispatch>, + options: InitOptions ) => WrappedMapDispatchToProps - initMergeProps: ( - dispatch: Dispatch, - options: PureSelectorFactoryComparisonOptions + readonly initMergeProps: ( + dispatch: Dispatch>, + options: InitOptions ) => MergeProps }