From 9c7ca0e12fd44727a35e38a47c859dab1abd9153 Mon Sep 17 00:00:00 2001 From: tony-go Date: Tue, 29 Jun 2021 21:56:09 +0200 Subject: [PATCH 1/4] chore(mapStateToProps): move to ts first pass --- ...{mapStateToProps.js => mapStateToProps.ts} | 10 ++++-- .../{wrapMapToProps.js => wrapMapToProps.ts} | 36 +++++++++++++------ 2 files changed, 32 insertions(+), 14 deletions(-) rename src/connect/{mapStateToProps.js => mapStateToProps.ts} (52%) rename src/connect/{wrapMapToProps.js => wrapMapToProps.ts} (73%) diff --git a/src/connect/mapStateToProps.js b/src/connect/mapStateToProps.ts similarity index 52% rename from src/connect/mapStateToProps.js rename to src/connect/mapStateToProps.ts index 6bfc0b368..2dcd7e7c3 100644 --- a/src/connect/mapStateToProps.js +++ b/src/connect/mapStateToProps.ts @@ -1,12 +1,16 @@ -import { wrapMapToPropsConstant, wrapMapToPropsFunc } from './wrapMapToProps' +import { + MapToProps, + wrapMapToPropsConstant, + wrapMapToPropsFunc, +} from './wrapMapToProps' -export function whenMapStateToPropsIsFunction(mapStateToProps) { +export function whenMapStateToPropsIsFunction(mapStateToProps?: MapToProps) { return typeof mapStateToProps === 'function' ? wrapMapToPropsFunc(mapStateToProps, 'mapStateToProps') : undefined } -export function whenMapStateToPropsIsMissing(mapStateToProps) { +export function whenMapStateToPropsIsMissing(mapStateToProps?: MapToProps) { return !mapStateToProps ? wrapMapToPropsConstant(() => ({})) : undefined } diff --git a/src/connect/wrapMapToProps.js b/src/connect/wrapMapToProps.ts similarity index 73% rename from src/connect/wrapMapToProps.js rename to src/connect/wrapMapToProps.ts index 53ff341ff..c456432ae 100644 --- a/src/connect/wrapMapToProps.js +++ b/src/connect/wrapMapToProps.ts @@ -1,7 +1,16 @@ +import { Dispatch } from 'redux' + import verifyPlainObject from '../utils/verifyPlainObject' -export function wrapMapToPropsConstant(getConstant) { - return function initConstantSelector(dispatch, options) { +export type MapToProps = { + (stateOrDispatch: any, ownProps?: any): any + dependsOnOwnProps: boolean +} + +export function wrapMapToPropsConstant( + getConstant: (dispatch: Dispatch, options: any) => void +) { + return function initConstantSelector(dispatch: Dispatch, options: any) { const constant = getConstant(dispatch, options) function constantSelector() { @@ -19,9 +28,8 @@ export function wrapMapToPropsConstant(getConstant) { // A length of one signals that mapToProps does not depend on props from the parent component. // A length of zero is assumed to mean mapToProps is getting args via arguments or ...args and // therefore not reporting its length accurately.. -export function getDependsOnOwnProps(mapToProps) { - return mapToProps.dependsOnOwnProps !== null && - mapToProps.dependsOnOwnProps !== undefined +export function getDependsOnOwnProps(mapToProps: MapToProps) { + return mapToProps?.dependsOnOwnProps ? Boolean(mapToProps.dependsOnOwnProps) : mapToProps.length !== 1 } @@ -38,20 +46,26 @@ export function getDependsOnOwnProps(mapToProps) { // * On first call, verifies the first result is a plain object, in order to warn // the developer that their mapToProps function is not returning a valid result. // -export function wrapMapToPropsFunc(mapToProps, methodName) { - return function initProxySelector(dispatch, { displayName }) { - const proxy = function mapToPropsProxy(stateOrDispatch, ownProps) { +export function wrapMapToPropsFunc(mapToProps: MapToProps, methodName: string) { + return function initProxySelector( + dispatch: Dispatch, + { displayName }: { displayName: string } + ) { + const proxy = function mapToPropsProxy( + stateOrDispatch: any, + ownProps: any + ): any { return proxy.dependsOnOwnProps ? proxy.mapToProps(stateOrDispatch, ownProps) - : proxy.mapToProps(stateOrDispatch) + : proxy.mapToProps(stateOrDispatch, null) } // allow detectFactoryAndVerify to get ownProps proxy.dependsOnOwnProps = true proxy.mapToProps = function detectFactoryAndVerify( - stateOrDispatch, - ownProps + stateOrDispatch: any, + ownProps: any ) { proxy.mapToProps = mapToProps proxy.dependsOnOwnProps = getDependsOnOwnProps(mapToProps) From 7d8fa8a2ddc31b228fa7829285df2e04863aeb0a Mon Sep 17 00:00:00 2001 From: tony-go Date: Wed, 30 Jun 2021 08:39:15 +0200 Subject: [PATCH 2/4] fix(mapStateToProps): add Fix later type and unknow --- src/connect/wrapMapToProps.ts | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/connect/wrapMapToProps.ts b/src/connect/wrapMapToProps.ts index c456432ae..ca20022f5 100644 --- a/src/connect/wrapMapToProps.ts +++ b/src/connect/wrapMapToProps.ts @@ -1,17 +1,23 @@ import { Dispatch } from 'redux' +import { FixTypeLater } from '../types' import verifyPlainObject from '../utils/verifyPlainObject' export type MapToProps = { - (stateOrDispatch: any, ownProps?: any): any + (stateOrDispatch: FixTypeLater, ownProps?: unknown): FixTypeLater dependsOnOwnProps: boolean } export function wrapMapToPropsConstant( - getConstant: (dispatch: Dispatch, options: any) => void + // * Note: + // It seems that the dispatch identifier here + // could be dispatch in some cases (ex: whenMapDispatchToPropsIsMissing) + // and state in some others (ex: whenMapStateToPropsIsMissing) + // + getConstant: (dispatch: Dispatch) => FixTypeLater ) { - return function initConstantSelector(dispatch: Dispatch, options: any) { - const constant = getConstant(dispatch, options) + return function initConstantSelector(dispatch: Dispatch) { + const constant = getConstant(dispatch) function constantSelector() { return constant @@ -52,9 +58,9 @@ export function wrapMapToPropsFunc(mapToProps: MapToProps, methodName: string) { { displayName }: { displayName: string } ) { const proxy = function mapToPropsProxy( - stateOrDispatch: any, - ownProps: any - ): any { + stateOrDispatch: FixTypeLater, + ownProps: unknown + ): FixTypeLater { return proxy.dependsOnOwnProps ? proxy.mapToProps(stateOrDispatch, ownProps) : proxy.mapToProps(stateOrDispatch, null) @@ -64,8 +70,8 @@ export function wrapMapToPropsFunc(mapToProps: MapToProps, methodName: string) { proxy.dependsOnOwnProps = true proxy.mapToProps = function detectFactoryAndVerify( - stateOrDispatch: any, - ownProps: any + stateOrDispatch: FixTypeLater, + ownProps: unknown ) { proxy.mapToProps = mapToProps proxy.dependsOnOwnProps = getDependsOnOwnProps(mapToProps) From bc1c647d50a3f2f60f0a9ea4fd316b580a1adca7 Mon Sep 17 00:00:00 2001 From: tony-go Date: Wed, 30 Jun 2021 23:28:36 +0200 Subject: [PATCH 3/4] fix: connect test --- test/components/connect.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/components/connect.spec.js b/test/components/connect.spec.js index b6cac31f1..25f97a75c 100644 --- a/test/components/connect.spec.js +++ b/test/components/connect.spec.js @@ -2660,7 +2660,7 @@ describe('React', () => { store.dispatch({ type: 'test' }) }) - expect(initialOwnProps).toBe(undefined) + expect(initialOwnProps).toBe(null) expect(initialState).not.toBe(undefined) expect(secondaryOwnProps).not.toBe(undefined) expect(secondaryOwnProps.name).toBe('a') From 413732028fb959005c61ad2516b13b8f7a30b8fe Mon Sep 17 00:00:00 2001 From: tony-go Date: Thu, 1 Jul 2021 15:13:00 +0200 Subject: [PATCH 4/4] feat: enrich types --- src/connect/wrapMapToProps.ts | 38 ++++++++++++++++++++------------- test/components/connect.spec.js | 2 +- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/connect/wrapMapToProps.ts b/src/connect/wrapMapToProps.ts index ca20022f5..f2d5775eb 100644 --- a/src/connect/wrapMapToProps.ts +++ b/src/connect/wrapMapToProps.ts @@ -3,18 +3,23 @@ import { Dispatch } from 'redux' import { FixTypeLater } from '../types' import verifyPlainObject from '../utils/verifyPlainObject' -export type MapToProps = { - (stateOrDispatch: FixTypeLater, ownProps?: unknown): FixTypeLater - dependsOnOwnProps: boolean +type AnyState = { [key: string]: any } +type StateOrDispatch = S | Dispatch + +type AnyProps = { [key: string]: any } + +export type MapToProps

= { + (stateOrDispatch: StateOrDispatch, ownProps?: P): FixTypeLater + dependsOnOwnProps?: boolean } export function wrapMapToPropsConstant( // * Note: - // It seems that the dispatch identifier here - // could be dispatch in some cases (ex: whenMapDispatchToPropsIsMissing) - // and state in some others (ex: whenMapStateToPropsIsMissing) + // It seems that the dispatch argument + // could be a dispatch function in some cases (ex: whenMapDispatchToPropsIsMissing) + // and a state object in some others (ex: whenMapStateToPropsIsMissing) // - getConstant: (dispatch: Dispatch) => FixTypeLater + getConstant: (dispatch: Dispatch) => { dispatch?: Dispatch } ) { return function initConstantSelector(dispatch: Dispatch) { const constant = getConstant(dispatch) @@ -52,27 +57,30 @@ export function getDependsOnOwnProps(mapToProps: MapToProps) { // * On first call, verifies the first result is a plain object, in order to warn // the developer that their mapToProps function is not returning a valid result. // -export function wrapMapToPropsFunc(mapToProps: MapToProps, methodName: string) { +export function wrapMapToPropsFunc

( + mapToProps: MapToProps, + methodName: string +) { return function initProxySelector( dispatch: Dispatch, { displayName }: { displayName: string } ) { const proxy = function mapToPropsProxy( - stateOrDispatch: FixTypeLater, - ownProps: unknown - ): FixTypeLater { + stateOrDispatch: StateOrDispatch, + ownProps?: P + ): MapToProps { return proxy.dependsOnOwnProps ? proxy.mapToProps(stateOrDispatch, ownProps) - : proxy.mapToProps(stateOrDispatch, null) + : proxy.mapToProps(stateOrDispatch, undefined) } // allow detectFactoryAndVerify to get ownProps proxy.dependsOnOwnProps = true proxy.mapToProps = function detectFactoryAndVerify( - stateOrDispatch: FixTypeLater, - ownProps: unknown - ) { + stateOrDispatch: StateOrDispatch, + ownProps?: P + ): MapToProps { proxy.mapToProps = mapToProps proxy.dependsOnOwnProps = getDependsOnOwnProps(mapToProps) let props = proxy(stateOrDispatch, ownProps) diff --git a/test/components/connect.spec.js b/test/components/connect.spec.js index 25f97a75c..b6cac31f1 100644 --- a/test/components/connect.spec.js +++ b/test/components/connect.spec.js @@ -2660,7 +2660,7 @@ describe('React', () => { store.dispatch({ type: 'test' }) }) - expect(initialOwnProps).toBe(null) + expect(initialOwnProps).toBe(undefined) expect(initialState).not.toBe(undefined) expect(secondaryOwnProps).not.toBe(undefined) expect(secondaryOwnProps.name).toBe('a')