From 756349c67c53c76888b575abe1c7e545378b72fe Mon Sep 17 00:00:00 2001 From: Boris Sergeyev Date: Thu, 22 Nov 2018 21:43:51 +0100 Subject: [PATCH 1/6] [react-redux] fixed mistreating of action thunk creator parameters --- types/react-redux/index.d.ts | 11 +++++++--- types/react-redux/react-redux-tests.tsx | 27 ++++++++++++++++--------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/types/react-redux/index.d.ts b/types/react-redux/index.d.ts index 2f919581f4..1cccae6d01 100644 --- a/types/react-redux/index.d.ts +++ b/types/react-redux/index.d.ts @@ -13,7 +13,7 @@ // Anatoli Papirovski // Boris Sergeyev // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.8 +// TypeScript Version: 3.0 // Known Issue: // There is a known issue in TypeScript, which doesn't allow decorators to change the signature of the classes @@ -112,9 +112,14 @@ export type InferableComponentEnhancerWithProps = export type InferableComponentEnhancer = InferableComponentEnhancerWithProps; +export type WrappedThunkActionCreator any> = + TActionCreator extends (...args: infer TParams) => (...args: any[]) => infer TReturn + ? (...args: TParams) => TReturn + : TActionCreator; + export type HandleThunkActionCreator = - TActionCreator extends (...args: any[]) => (...args: any[]) => any - ? ReturnType + TActionCreator extends (...args: any[]) => any + ? WrappedThunkActionCreator : TActionCreator; // redux-thunk middleware returns thunk's return value from dispatch call diff --git a/types/react-redux/react-redux-tests.tsx b/types/react-redux/react-redux-tests.tsx index aff8515e87..f47683047e 100644 --- a/types/react-redux/react-redux-tests.tsx +++ b/types/react-redux/react-redux-tests.tsx @@ -102,20 +102,27 @@ function MapDispatch() { } function MapDispatchWithThunkActionCreators() { - class TestComponent extends React.Component<{ - foo: string, - onClick(): void, - thunkAction(): Promise - }> {} - - const mapDispatchToProps = () => ({ - onClick: () => {}, - thunkAction: () => async () => {} + const simpleAction = (payload: boolean) => ({ + type: 'SIMPLE_ACTION', + payload, }); + const thunkAction = (param1: number, param2: string) => ( + async (dispatch: Dispatch, { foo }: OwnProps) => { + return foo; + } + ); + interface OwnProps { + foo: string; + } + interface TestComponentProps extends OwnProps { + simpleAction: typeof simpleAction; + thunkAction(param1: number, param2: string): Promise; + } + class TestComponent extends React.Component {} const Test = connect( null, - mapDispatchToProps, + ({ simpleAction, thunkAction }), )(TestComponent); const verify = ; From 35d989dce077cdd42be9943a53895eeebf569fb8 Mon Sep 17 00:00:00 2001 From: Boris Sergeyev Date: Thu, 22 Nov 2018 22:16:23 +0100 Subject: [PATCH 2/6] [react-redux] bumped TS versions of packages dependent on react-redux --- types/mirrorx/index.d.ts | 2 +- types/next-redux-saga/index.d.ts | 2 +- types/next-redux-wrapper/index.d.ts | 2 +- types/react-intl-redux/index.d.ts | 2 +- types/react-lifecycle-component/index.d.ts | 2 +- types/react-redux-toastr/index.d.ts | 2 +- types/react-router-redux/index.d.ts | 2 +- types/redux-auth-wrapper/index.d.ts | 2 +- types/redux-devtools/index.d.ts | 2 +- types/redux-form/index.d.ts | 2 +- types/redux-form/v6/index.d.ts | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/types/mirrorx/index.d.ts b/types/mirrorx/index.d.ts index 443712c325..e2fa0ee465 100644 --- a/types/mirrorx/index.d.ts +++ b/types/mirrorx/index.d.ts @@ -2,7 +2,7 @@ // Project: https://github.com/mirrorjs/mirror // Definitions by: Aaronphy // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.8 +// TypeScript Version: 3.0 import * as H from 'history'; diff --git a/types/next-redux-saga/index.d.ts b/types/next-redux-saga/index.d.ts index b7575fba16..0366868d97 100644 --- a/types/next-redux-saga/index.d.ts +++ b/types/next-redux-saga/index.d.ts @@ -2,7 +2,7 @@ // Project: https://github.com/bmealhouse/next-redux-saga // Definitions by: Leo Cavalcante // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.8 +// TypeScript Version: 3.0 import { ComponentType } from "react"; diff --git a/types/next-redux-wrapper/index.d.ts b/types/next-redux-wrapper/index.d.ts index 16af858743..cbf56579d5 100644 --- a/types/next-redux-wrapper/index.d.ts +++ b/types/next-redux-wrapper/index.d.ts @@ -3,7 +3,7 @@ // Definitions by: Steve // Jungwoo-An // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.8 +// TypeScript Version: 3.0 /// diff --git a/types/react-intl-redux/index.d.ts b/types/react-intl-redux/index.d.ts index 9d9e805df9..4410e7c019 100644 --- a/types/react-intl-redux/index.d.ts +++ b/types/react-intl-redux/index.d.ts @@ -2,7 +2,7 @@ // Project: https://github.com/ratson/react-intl-redux // Definitions by: Karol Janyst // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.8 +// TypeScript Version: 3.0 import { Action, AnyAction } from "redux" import { Provider as ReduxProvider } from "react-redux" diff --git a/types/react-lifecycle-component/index.d.ts b/types/react-lifecycle-component/index.d.ts index 315d04f7fb..bb6dc65dd8 100644 --- a/types/react-lifecycle-component/index.d.ts +++ b/types/react-lifecycle-component/index.d.ts @@ -2,7 +2,7 @@ // Project: https://github.com/JamieDixon/react-lifecycle-component // Definitions by: Alexander Fisher // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.8 +// TypeScript Version: 3.0 import { ComponentLifecycle, Component, ComponentClass } from 'react'; import { Connect } from 'react-redux'; diff --git a/types/react-redux-toastr/index.d.ts b/types/react-redux-toastr/index.d.ts index fc11da9c43..9a7a115725 100644 --- a/types/react-redux-toastr/index.d.ts +++ b/types/react-redux-toastr/index.d.ts @@ -4,7 +4,7 @@ // Artyom Stukans // Mika Kuitunen // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.8 +// TypeScript Version: 3.0 import { Component } from 'react'; import { Action, Reducer } from 'redux'; diff --git a/types/react-router-redux/index.d.ts b/types/react-router-redux/index.d.ts index 9dfbd58c11..7abdc88505 100644 --- a/types/react-router-redux/index.d.ts +++ b/types/react-router-redux/index.d.ts @@ -4,7 +4,7 @@ // Shoya Tanaka // Mykolas // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.8 +// TypeScript Version: 3.0 import { Store, diff --git a/types/redux-auth-wrapper/index.d.ts b/types/redux-auth-wrapper/index.d.ts index 728be4a54b..3ec88b50dc 100644 --- a/types/redux-auth-wrapper/index.d.ts +++ b/types/redux-auth-wrapper/index.d.ts @@ -2,7 +2,7 @@ // Project: https://github.com/mjrussell/redux-auth-wrapper // Definitions by: Karol Janyst // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.8 +// TypeScript Version: 3.0 import { ComponentClass, StatelessComponent, ComponentType, ReactType } from "react"; diff --git a/types/redux-devtools/index.d.ts b/types/redux-devtools/index.d.ts index 234fb9a4bb..ddead025ff 100644 --- a/types/redux-devtools/index.d.ts +++ b/types/redux-devtools/index.d.ts @@ -2,7 +2,7 @@ // Project: https://github.com/gaearon/redux-devtools // Definitions by: Petryshyn Sergii // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.8 +// TypeScript Version: 3.0 import * as React from 'react'; import { GenericStoreEnhancer } from 'redux'; diff --git a/types/redux-form/index.d.ts b/types/redux-form/index.d.ts index e80c196c0a..5851728369 100644 --- a/types/redux-form/index.d.ts +++ b/types/redux-form/index.d.ts @@ -12,7 +12,7 @@ // Maddi Joyce // Kamil Wojcik // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.9 +// TypeScript Version: 3.0 import { ComponentClass, StatelessComponent, diff --git a/types/redux-form/v6/index.d.ts b/types/redux-form/v6/index.d.ts index a8209a7643..5127457884 100644 --- a/types/redux-form/v6/index.d.ts +++ b/types/redux-form/v6/index.d.ts @@ -2,7 +2,7 @@ // Project: https://github.com/erikras/redux-form // Definitions by: Carson Full , Daniel Lytkin , Karol Janyst , Luka Zakrajsek // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.8 +// TypeScript Version: 3.0 import { ComponentClass, From 2d5a8af9f819fad592387f8b4ce3731643125b05 Mon Sep 17 00:00:00 2001 From: Boris Sergeyev Date: Thu, 22 Nov 2018 22:18:01 +0100 Subject: [PATCH 3/6] [react-redux] used whitespace consistently (no tabs) --- types/react-redux/index.d.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/types/react-redux/index.d.ts b/types/react-redux/index.d.ts index 1cccae6d01..bf65d89fd5 100644 --- a/types/react-redux/index.d.ts +++ b/types/react-redux/index.d.ts @@ -65,11 +65,11 @@ export type AdvancedComponentDecorator = * DecorationTargetProps[P] definition, its definition will be that of InjectedProps[P] */ export type Matching = { - [P in keyof DecorationTargetProps]: P extends keyof InjectedProps - ? InjectedProps[P] extends DecorationTargetProps[P] - ? DecorationTargetProps[P] - : InjectedProps[P] - : DecorationTargetProps[P]; + [P in keyof DecorationTargetProps]: P extends keyof InjectedProps + ? InjectedProps[P] extends DecorationTargetProps[P] + ? DecorationTargetProps[P] + : InjectedProps[P] + : DecorationTargetProps[P]; }; /** @@ -95,16 +95,16 @@ export type GetProps = C extends ComponentType ? P : never; // Applies LibraryManagedAttributes (proper handling of defaultProps // and propTypes), as well as defines WrappedComponent. export type ConnectedComponentClass = ComponentClass> & { - WrappedComponent: C; + WrappedComponent: C; }; // Injects props and removes them from the prop requirements. // Will not pass through the injected props if they are passed in during // render. Also adds new prop requirements from TNeedsProps. export type InferableComponentEnhancerWithProps = - >>>( - component: C - ) => ConnectedComponentClass, keyof Shared>> & TNeedsProps>; + >>>( + component: C + ) => ConnectedComponentClass, keyof Shared>> & TNeedsProps>; // Injects props and removes them from the prop requirements. // Will not pass through the injected props if they are passed in during From 9fa2b6599f6309a7e33e5b5ab1387537ed68d9df Mon Sep 17 00:00:00 2001 From: Boris Sergeyev Date: Mon, 26 Nov 2018 22:18:35 +0100 Subject: [PATCH 4/6] [react-redux] extended ThunkActionCreator testsuite to check all overloads --- types/react-redux/react-redux-tests.tsx | 59 ++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/types/react-redux/react-redux-tests.tsx b/types/react-redux/react-redux-tests.tsx index f47683047e..554ace09ff 100644 --- a/types/react-redux/react-redux-tests.tsx +++ b/types/react-redux/react-redux-tests.tsx @@ -120,12 +120,61 @@ function MapDispatchWithThunkActionCreators() { } class TestComponent extends React.Component {} - const Test = connect( - null, - ({ simpleAction, thunkAction }), - )(TestComponent); + const mapStateToProps = ({ foo }: { foo: string }) => ({ foo }); + const mapDispatchToProps = { simpleAction, thunkAction }; - const verify = ; + const Test1 = connect(null, mapDispatchToProps)(TestComponent); + const Test2 = connect(mapStateToProps, mapDispatchToProps)(TestComponent); + const Test3 = connect( + null, mapDispatchToProps, null, { storeKey: 'somekey' } + )(TestComponent); + const Test4 = connect( + mapStateToProps, mapDispatchToProps, null, { storeKey: 'somekey' } + )(TestComponent); + const verify =
+ ; + + ; + +
; +} + +function MapManualDispatchThatLooksLikeThunk() { + interface OwnProps { + foo: string; + } + interface TestComponentProps extends OwnProps { + remove: (item: string) => () => object; + } + class TestComponent extends React.Component { + render() { + return
; + } + } + + const mapStateToProps = ({ foo }: { foo: string }) => ({ foo }); + function mapDispatchToProps(dispatch: Dispatch) { + return { + remove(item: string) { + return () => dispatch({ type: 'REMOVE_ITEM', item }); + } + }; + } + + const Test1 = connect(null, mapDispatchToProps)(TestComponent); + const Test2 = connect(mapStateToProps, mapDispatchToProps)(TestComponent); + const Test3 = connect( + null, mapDispatchToProps, null, { storeKey: 'somekey' } + )(TestComponent); + const Test4 = connect( + mapStateToProps, mapDispatchToProps, null, { storeKey: 'somekey' } + )(TestComponent); + const verify =
+ ; + + ; + +
; } function MapStateAndDispatchObject() { From 8cbf6d938de2e838a4f3cc9695576958ed55f4c3 Mon Sep 17 00:00:00 2001 From: Boris Sergeyev Date: Mon, 26 Nov 2018 22:19:18 +0100 Subject: [PATCH 5/6] [react-redux] fixed type definitions to pass extended tests --- types/react-redux/index.d.ts | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/types/react-redux/index.d.ts b/types/react-redux/index.d.ts index bf65d89fd5..dc8a9af912 100644 --- a/types/react-redux/index.d.ts +++ b/types/react-redux/index.d.ts @@ -160,7 +160,12 @@ export interface Connect { ( mapStateToProps: null | undefined, - mapDispatchToProps: MapDispatchToPropsParam + mapDispatchToProps: MapDispatchToPropsNonObject + ): InferableComponentEnhancerWithProps; + + ( + mapStateToProps: null | undefined, + mapDispatchToProps: TDispatchProps, ): InferableComponentEnhancerWithProps< WithThunkActionCreators, TOwnProps @@ -168,7 +173,12 @@ export interface Connect { ( mapStateToProps: MapStateToPropsParam, - mapDispatchToProps: MapDispatchToPropsParam + mapDispatchToProps: MapDispatchToPropsNonObject + ): InferableComponentEnhancerWithProps; + + ( + mapStateToProps: MapStateToPropsParam, + mapDispatchToProps: TDispatchProps, ): InferableComponentEnhancerWithProps< TStateProps & WithThunkActionCreators, TOwnProps @@ -208,7 +218,14 @@ export interface Connect { ( mapStateToProps: null | undefined, - mapDispatchToProps: MapDispatchToPropsParam, + mapDispatchToProps: MapDispatchToPropsNonObject, + mergeProps: null | undefined, + options: Options<{}, TStateProps, TOwnProps> + ): InferableComponentEnhancerWithProps; + + ( + mapStateToProps: null | undefined, + mapDispatchToProps: TDispatchProps, mergeProps: null | undefined, options: Options<{}, TStateProps, TOwnProps> ): InferableComponentEnhancerWithProps< @@ -218,7 +235,14 @@ export interface Connect { ( mapStateToProps: MapStateToPropsParam, - mapDispatchToProps: MapDispatchToPropsParam, + mapDispatchToProps: MapDispatchToPropsNonObject, + mergeProps: null | undefined, + options: Options + ): InferableComponentEnhancerWithProps; + + ( + mapStateToProps: MapStateToPropsParam, + mapDispatchToProps: TDispatchProps, mergeProps: null | undefined, options: Options ): InferableComponentEnhancerWithProps< @@ -248,10 +272,12 @@ export type MapDispatchToProps = MapDispatchToPropsFunction | TDispatchProps; export type MapDispatchToPropsFactory = - (dispatch: Dispatch, ownProps: TOwnProps) => MapDispatchToProps; + (dispatch: Dispatch, ownProps: TOwnProps) => MapDispatchToPropsFunction; export type MapDispatchToPropsParam = MapDispatchToPropsFactory | MapDispatchToProps; +export type MapDispatchToPropsNonObject = MapDispatchToPropsFactory | MapDispatchToPropsFunction; + export type MergeProps = (stateProps: TStateProps, dispatchProps: TDispatchProps, ownProps: TOwnProps) => TMergedProps; From 84bc355df06ea07679ab0634483c08f76ac4bb7c Mon Sep 17 00:00:00 2001 From: Boris Sergeyev Date: Tue, 27 Nov 2018 07:18:16 +0100 Subject: [PATCH 6/6] [react-redux] improved naming of higher-order-type that handles thunks --- types/react-redux/index.d.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/types/react-redux/index.d.ts b/types/react-redux/index.d.ts index dc8a9af912..bcbcced0bd 100644 --- a/types/react-redux/index.d.ts +++ b/types/react-redux/index.d.ts @@ -112,19 +112,19 @@ export type InferableComponentEnhancerWithProps = export type InferableComponentEnhancer = InferableComponentEnhancerWithProps; -export type WrappedThunkActionCreator any> = +export type InferThunkActionCreatorType any> = TActionCreator extends (...args: infer TParams) => (...args: any[]) => infer TReturn ? (...args: TParams) => TReturn : TActionCreator; export type HandleThunkActionCreator = TActionCreator extends (...args: any[]) => any - ? WrappedThunkActionCreator + ? InferThunkActionCreatorType : TActionCreator; // redux-thunk middleware returns thunk's return value from dispatch call // https://github.com/reduxjs/redux-thunk#composition -export type WithThunkActionCreators = +export type ResolveThunks = TDispatchProps extends { [key: string]: any } ? { [C in keyof TDispatchProps]: HandleThunkActionCreator @@ -167,7 +167,7 @@ export interface Connect { mapStateToProps: null | undefined, mapDispatchToProps: TDispatchProps, ): InferableComponentEnhancerWithProps< - WithThunkActionCreators, + ResolveThunks, TOwnProps >; @@ -180,7 +180,7 @@ export interface Connect { mapStateToProps: MapStateToPropsParam, mapDispatchToProps: TDispatchProps, ): InferableComponentEnhancerWithProps< - TStateProps & WithThunkActionCreators, + TStateProps & ResolveThunks, TOwnProps >; @@ -229,7 +229,7 @@ export interface Connect { mergeProps: null | undefined, options: Options<{}, TStateProps, TOwnProps> ): InferableComponentEnhancerWithProps< - WithThunkActionCreators, + ResolveThunks, TOwnProps >; @@ -246,7 +246,7 @@ export interface Connect { mergeProps: null | undefined, options: Options ): InferableComponentEnhancerWithProps< - TStateProps & WithThunkActionCreators, + TStateProps & ResolveThunks, TOwnProps >; // tslint:enable:no-unnecessary-generics