From 1717f5656e1fd8cea563dcd8210c558e12ed09f3 Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Thu, 18 Apr 2019 01:17:02 +0300 Subject: [PATCH] [IMP] redux-saga-routines: support version 3.1 (#34760) * [FIX] redux-saga-routines: loosen type definitions * [IMP] redux-saga-routines: support 3.1 --- types/redux-saga-routines/index.d.ts | 347 +++++++++++++++--- .../redux-saga-routines-tests.ts | 49 +++ 2 files changed, 349 insertions(+), 47 deletions(-) diff --git a/types/redux-saga-routines/index.d.ts b/types/redux-saga-routines/index.d.ts index 9efceeedae..9dced1f32f 100644 --- a/types/redux-saga-routines/index.d.ts +++ b/types/redux-saga-routines/index.d.ts @@ -1,4 +1,4 @@ -// Type definitions for redux-saga-routines 3.0 +// Type definitions for redux-saga-routines 3.1 // Project: https://github.com/afitiskin/redux-saga-routines // Definitions by: Alexey Pelykh // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped @@ -9,8 +9,6 @@ import { Action, ActionMeta, createAction, - ActionFunctions, - ActionWithMetaFunctions, ActionFunction0, ActionFunction1, ActionFunction2, @@ -19,27 +17,99 @@ import { ActionFunctionAny, } from 'redux-actions'; import { FormSubmitHandler } from 'redux-form'; +import { string } from 'prop-types'; -export function routinePromiseWatcherSaga(): Generator; +export function routinePromiseWatcherSaga(): IterableIterator; -export type ActionCreator = ActionFunctions | ActionWithMetaFunctions; +export type RoutineStages = 'TRIGGER' | 'REQUEST' | 'SUCCESS' | 'FAILURE' | 'FULFILL'; + +export type ActionCreatorFunction = ActionFunctionAny< + Action | ActionMeta +>; export type Routine< - TTriggerActionCreator = ActionCreator + TTriggerActionCreator = ActionCreatorFunction, + TRequestActionCreator = ActionCreatorFunction, + TSuccessActionCreator = ActionCreatorFunction, + TFailureActionCreator = ActionCreatorFunction, + TFulfillActionCreator = ActionCreatorFunction > = TTriggerActionCreator & { - TRIGGER: string; - REQUEST: string; - SUCCESS: string; - FAILURE: string; - FULFILL: string; + [key in RoutineStages]: string; } & { trigger: TTriggerActionCreator; - request: ActionCreator; - success: ActionCreator; - failure: ActionCreator; - fulfill: ActionCreator; + request: TRequestActionCreator; + success: TSuccessActionCreator; + failure: TFailureActionCreator; + fulfill: TFulfillActionCreator; }; +export type UnifiedRoutine = Routine< + TActionCreator, + TActionCreator, + TActionCreator, + TActionCreator, + TActionCreator +>; + +export type ResolveFunctionReturnType = + TFunction extends (...args: any[]) => infer TReturn ? TReturn : undefined; + +export type ResolveFunctionArg1Type = + TFunction extends (arg1: infer TArg1, ...args: any[]) => any ? TArg1 : undefined; + +export type ResolveFunctionArg2Type = + TFunction extends (arg1: any, arg2: infer TArg1, ...args: any[]) => any ? TArg1 : undefined; + +export type ResolveFunctionArg3Type = + TFunction extends (arg1: any, arg2: any, arg3: infer TArg1, ...args: any[]) => any ? TArg1 : undefined; + +export type ResolveFunctionArg4Type = + TFunction extends (arg1: any, arg2: any, arg3: any, arg4: infer TArg1, ...args: any[]) => any ? TArg1 : undefined; + +export type ResolveActionCreatorByPayload< + TPayloadCreator, + TPayload = ResolveFunctionReturnType, + TArg1 = ResolveFunctionArg1Type, + TArg2 = ResolveFunctionArg2Type, + TArg3 = ResolveFunctionArg3Type, + TArg4 = ResolveFunctionArg4Type +> = + TPayloadCreator extends ActionFunction0 ? ActionFunction0> : + TPayloadCreator extends ActionFunction1 ? ActionFunction1> : + TPayloadCreator extends ActionFunction2 ? ActionFunction2> : + TPayloadCreator extends ActionFunction3 ? ActionFunction3> : + TPayloadCreator extends ActionFunction4 ? ActionFunction4> : ActionFunctionAny>; + +export type ResolveActionCreatorByMeta< + TMetaCreator, + TMeta = ResolveFunctionReturnType, + TArg1 = ResolveFunctionArg1Type, + TArg2 = ResolveFunctionArg2Type, + TArg3 = ResolveFunctionArg3Type, + TArg4 = ResolveFunctionArg4Type +> = + TMetaCreator extends ActionFunction0 ? ActionFunction0> : + TMetaCreator extends ActionFunction1 ? ActionFunction1> : + TMetaCreator extends ActionFunction2 ? ActionFunction2> : + TMetaCreator extends ActionFunction3 ? ActionFunction3> : + TMetaCreator extends ActionFunction4 ? ActionFunction4> : ActionFunctionAny>; + +export type ResolveActionCreatorByPayloadMeta< + TPayloadCreator, + TMetaCreator, + TPayload = ResolveFunctionReturnType, + TMeta = ResolveFunctionReturnType, + TArg1 = ResolveFunctionArg1Type, + TArg2 = ResolveFunctionArg2Type, + TArg3 = ResolveFunctionArg3Type, + TArg4 = ResolveFunctionArg4Type +> = + TMetaCreator extends ActionFunction0 ? ActionFunction0> : + TMetaCreator extends ActionFunction1 ? ActionFunction1> : + TMetaCreator extends ActionFunction2 ? ActionFunction2> : + TMetaCreator extends ActionFunction3 ? ActionFunction3> : + TMetaCreator extends ActionFunction4 ? ActionFunction4> : ActionFunctionAny>; + export interface ReduxFormPayload { values: TFormData; props: TProps; @@ -88,73 +158,256 @@ export function bindPromiseCreators( export const ROUTINE_PROMISE_ACTION: string; -// TODO: support https://github.com/afitiskin/redux-saga-routines/commit/9eb5a240df25d771f9dfbd4cb90e898d111242ab +// NOTE: Default payloadCreator is identity (x => x) +// NOTE: Same payloadCreator is used for all actions of the routine +export function createRoutine< + Payload = any +>( + typePrefix: string +): UnifiedRoutine< + (payload?: Payload) => Action +>; -export function createRoutine( +// NOTE: Same payloadCreator is used for all actions of the routine +export function createRoutine< + Payload +>( typePrefix: string, -): Routine>>; + payloadCreator: ActionFunction0 +): UnifiedRoutine< + ActionFunction0> +>; -export function createRoutine( - typePrefix: string, - payloadCreator: ActionFunction0, -): Routine>>; - -export function createRoutine( +// NOTE: Same payloadCreator is used for all actions of the routine +export function createRoutine< + Payload, + Arg1 +>( typePrefix: string, payloadCreator: ActionFunction1, -): Routine>>; +): UnifiedRoutine< + ActionFunction1> +>; -export function createRoutine( +// NOTE: Same payloadCreator is used for all actions of the routine +export function createRoutine< + Payload, + Arg1, + Arg2 +>( typePrefix: string, payloadCreator: ActionFunction2, -): Routine>>; +): UnifiedRoutine< + ActionFunction2> +>; -export function createRoutine( +// NOTE: Same payloadCreator is used for all actions of the routine +export function createRoutine< + Payload, + Arg1, + Arg2, + Arg3 +>( typePrefix: string, payloadCreator: ActionFunction3, -): Routine>>; +): UnifiedRoutine< + ActionFunction3> +>; -export function createRoutine( +// NOTE: Same payloadCreator is used for all actions of the routine +export function createRoutine< + Payload, + Arg1, + Arg2, + Arg3, + Arg4 +>( typePrefix: string, payloadCreator: ActionFunction4, -): Routine>>; +): UnifiedRoutine< + ActionFunction4> +>; -export function createRoutine( - typePrefix: string, -): Routine>>; - -export function createRoutine( +// NOTE: Default payloadCreator is identity (x => x) +// NOTE: Same payloadCreator is used for all actions of the routine +export function createRoutine< + Meta +>( typePrefix: string, payloadCreator: null | undefined, metaCreator: ActionFunctionAny, -): Routine>>; +): UnifiedRoutine< + (payload?: any) => ActionMeta +>; -export function createRoutine( +// NOTE: Same payloadCreator is used for all actions of the routine +export function createRoutine< + Payload, + Meta +>( typePrefix: string, payloadCreator: ActionFunctionAny, metaCreator: ActionFunctionAny, -): Routine>>; +): UnifiedRoutine< + ActionFunctionAny> +>; -export function createRoutine( +// NOTE: Same payloadCreator is used for all actions of the routine +export function createRoutine< + Payload, + Meta, + Arg1 +>( typePrefix: string, payloadCreator: ActionFunction1, metaCreator: ActionFunction1, -): Routine>>; +): UnifiedRoutine< + ActionFunction1> +>; -export function createRoutine( +// NOTE: Same payloadCreator is used for all actions of the routine +export function createRoutine< + Payload, + Meta, + Arg1, + Arg2 +>( typePrefix: string, payloadCreator: ActionFunction2, metaCreator: ActionFunction2, -): Routine>>; +): UnifiedRoutine< + ActionFunction2> +>; -export function createRoutine( +// NOTE: Same payloadCreator is used for all actions of the routine +export function createRoutine< + Payload, + Meta, + Arg1, + Arg2, + Arg3 +>( typePrefix: string, payloadCreator: ActionFunction3, metaCreator: ActionFunction3, -): Routine>>; +): UnifiedRoutine< + ActionFunction3> +>; -export function createRoutine( +// NOTE: Same payloadCreator is used for all actions of the routine +export function createRoutine< + Payload, + Meta, + Arg1, + Arg2, + Arg3, + Arg4 +>( typePrefix: string, payloadCreator: ActionFunction4, metaCreator: ActionFunction4, -): Routine>>; +): UnifiedRoutine< + ActionFunction4> +>; + +export function createRoutine< + TTriggerPayloadCreator, + TRequestPayloadCreator, + TSuccessPayloadCreator, + TFailurePayloadCreator, + TFulfillPayloadCreator +>( + typePrefix: string, + payloadCreator: { + TRIGGER?: TTriggerPayloadCreator, + trigger?: TTriggerPayloadCreator, + REQUEST?: TRequestPayloadCreator, + request?: TRequestPayloadCreator, + SUCCESS?: TSuccessPayloadCreator, + success?: TSuccessPayloadCreator, + FAILURE?: TFailurePayloadCreator, + failure?: TFailurePayloadCreator, + FULFILL?: TFulfillPayloadCreator, + fulfill?: TFulfillPayloadCreator + } +): Routine< + ResolveActionCreatorByPayload, + ResolveActionCreatorByPayload, + ResolveActionCreatorByPayload, + ResolveActionCreatorByPayload, + ResolveActionCreatorByPayload +>; + +export function createRoutine< + TTriggerMetaCreator, + TRequestMetaCreator, + TSuccessMetaCreator, + TFailureMetaCreator, + TFulfillMetaCreator +>( + typePrefix: string, + payloadCreator: null | undefined, + metaCreator: { + TRIGGER?: TTriggerMetaCreator, + trigger?: TTriggerMetaCreator, + REQUEST?: TRequestMetaCreator, + request?: TRequestMetaCreator, + SUCCESS?: TSuccessMetaCreator, + success?: TSuccessMetaCreator, + FAILURE?: TFailureMetaCreator, + failure?: TFailureMetaCreator, + FULFILL?: TFulfillMetaCreator, + fulfill?: TFulfillMetaCreator + } +): Routine< + ResolveActionCreatorByMeta, + ResolveActionCreatorByMeta, + ResolveActionCreatorByMeta, + ResolveActionCreatorByMeta, + ResolveActionCreatorByMeta +>; + +export function createRoutine< + TTriggerPayloadCreator, + TRequestPayloadCreator, + TSuccessPayloadCreator, + TFailurePayloadCreator, + TFulfillPayloadCreator, + TTriggerMetaCreator, + TRequestMetaCreator, + TSuccessMetaCreator, + TFailureMetaCreator, + TFulfillMetaCreator +>( + typePrefix: string, + payloadCreator: { + TRIGGER?: TTriggerPayloadCreator, + trigger?: TTriggerPayloadCreator, + REQUEST?: TRequestPayloadCreator, + request?: TRequestPayloadCreator, + SUCCESS?: TSuccessPayloadCreator, + success?: TSuccessPayloadCreator, + FAILURE?: TFailurePayloadCreator, + failure?: TFailurePayloadCreator, + FULFILL?: TFulfillPayloadCreator, + fulfill?: TFulfillPayloadCreator + }, + metaCreator: { + TRIGGER?: TTriggerMetaCreator, + trigger?: TTriggerMetaCreator, + REQUEST?: TRequestMetaCreator, + request?: TRequestMetaCreator, + SUCCESS?: TSuccessMetaCreator, + success?: TSuccessMetaCreator, + FAILURE?: TFailureMetaCreator, + failure?: TFailureMetaCreator, + FULFILL?: TFulfillMetaCreator, + fulfill?: TFulfillMetaCreator + } +): Routine< + ResolveActionCreatorByPayloadMeta, + ResolveActionCreatorByPayloadMeta, + ResolveActionCreatorByPayloadMeta, + ResolveActionCreatorByPayloadMeta, + ResolveActionCreatorByPayloadMeta +>; diff --git a/types/redux-saga-routines/redux-saga-routines-tests.ts b/types/redux-saga-routines/redux-saga-routines-tests.ts index eb4f54bbf4..ad161db59e 100644 --- a/types/redux-saga-routines/redux-saga-routines-tests.ts +++ b/types/redux-saga-routines/redux-saga-routines-tests.ts @@ -8,3 +8,52 @@ import { ROUTINE_PROMISE_ACTION, createRoutine, } from 'redux-saga-routines'; + +import { + ActionFunction0, + ActionFunction1, + ActionFunctionAny, + Action +} from 'redux-actions'; + +const routine_anyargs = createRoutine('ANYARGS'); +routine_anyargs(); +routine_anyargs('string'); +routine_anyargs(42); +routine_anyargs.trigger(); +routine_anyargs.trigger('string'); +routine_anyargs.trigger(42); +routine_anyargs.request(); + +const routine_noargs = createRoutine('NOARGS', () => {}); +routine_noargs(); +routine_noargs.trigger(); +routine_noargs.trigger('string'); // $ExpectError +routine_noargs.trigger(42); // $ExpectError +routine_noargs.request(); + +const routine_strarg = createRoutine('STRARG', (x: string) => {}); +routine_strarg(); // $ExpectError +routine_strarg.trigger(); // $ExpectError +routine_strarg.trigger('string'); +routine_strarg.trigger(42); // $ExpectError +routine_strarg.request(); // $ExpectError +routine_strarg.request('string'); + +const routine_multiple_creators = createRoutine('MULTIPLE_CREATORS', { + trigger: () => {}, + REQUEST: (arg: number) => arg, + success: (a: object, b: object, c: object, d: object, e: number) => e, + fulfill: (result: string, content: any) => {}, +}); +routine_multiple_creators(); +routine_multiple_creators.trigger('string'); // $ExpectError +routine_multiple_creators.request(); // $ExpectError +routine_multiple_creators.request('string'); // $ExpectError +routine_multiple_creators.request(42); +routine_multiple_creators.success(); +routine_multiple_creators.success('string'); +routine_multiple_creators.success(42); +routine_multiple_creators.fulfill(); // $ExpectError +routine_multiple_creators.fulfill(1, 'string'); // $ExpectError +routine_multiple_creators.fulfill('string', {});