Skip to content

Instantly share code, notes, and snippets.

@apieceofbart
Forked from Vovan-VE/example.action-types.ts
Created September 9, 2019 14:04
Show Gist options
  • Save apieceofbart/8b5ab61f1bed29ef25f3b135818e5448 to your computer and use it in GitHub Desktop.
Save apieceofbart/8b5ab61f1bed29ef25f3b135818e5448 to your computer and use it in GitHub Desktop.

Revisions

  1. @Vovan-VE Vovan-VE revised this gist Aug 2, 2019. 2 changed files with 20 additions and 15 deletions.
    2 changes: 1 addition & 1 deletion example.actions.ts
    Original file line number Diff line number Diff line change
    @@ -2,7 +2,7 @@ import { ThunkAction } from '.../redux-thunk-promise';
    import { AppState } from 'store/';
    import { FETCH, FetchAction } from './types';

    export const fetchFoo = (): ThunkAction<void, AppState, null, FetchAction> =>
    export const fetchFoo = (): ThunkAction<void, AppState> =>
    (dispatch, getState) => {
    if (...) {
    dispatch({
    33 changes: 19 additions & 14 deletions redux-thunk-promise.d.ts
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,6 @@
    // https://github.com/pburtchaell/redux-promise-middleware/issues/253

    import { Action } from 'redux';
    import { AsyncAction as OrigAsyncAction } from 'redux-promise-middleware';
    import { ThunkDispatch as OrigThunkDispatch } from 'redux-thunk';

    // -----------------------------------
    // redux-promise-middleware extension
    @@ -17,16 +15,16 @@ declare type AsyncPayload<R = any> =
    data?: any;
    };

    export declare interface AsyncAction<R> extends OrigAsyncAction {
    payload?: AsyncPayload<R>;
    export declare interface AsyncAction<R = any> extends OrigAsyncAction {
    payload: AsyncPayload<R>;
    }

    type AsyncActionResult<A> = A extends AsyncAction<infer R> ? R : never;

    export type AsyncFulfilledAction<A extends AsyncAction, Type = string> = Omit<
    A,
    'type' | 'payload'
    > & {
    export type AsyncFulfilledAction<
    A extends AsyncAction,
    Type extends string = string
    > = Omit<A, 'type' | 'payload'> & {
    type: Type;
    payload: AsyncActionResult<A>;
    };
    @@ -36,17 +34,24 @@ type FulfilledDispatchResult<A extends AsyncAction> = {
    value: AsyncActionResult<A>;
    };

    export type AsyncDispatchReturns<T> = T extends AsyncAction
    ? Promise<FulfilledDispatchResult<T>>
    : T;

    // ----------------------
    // redux-thunk extension
    // ----------------------

    export declare interface ThunkDispatch<S, E, A extends Action>
    extends OrigThunkDispatch<S, E, A> {
    <A extends AsyncAction>(asyncAction: A): Promise<FulfilledDispatchResult<A>>;
    export type ThunkDispatchReturns<S, E, A> = A extends ThunkAction<infer R, S, E>
    ? R
    : A;

    export interface ThunkDispatch<S, E> {
    <A>(action: A): AsyncDispatchReturns<ThunkDispatchReturns<S, E, A>>;
    }

    export declare type ThunkAction<R, S, E, A extends Action> = (
    dispatch: ThunkDispatch<S, E, A>,
    export declare type ThunkAction<R, S, E = null> = (
    dispatch: ThunkDispatch<S, E>,
    getState: () => S,
    extraArgument: E,
    ) => R;
    ) => R;
  2. @Vovan-VE Vovan-VE created this gist Aug 2, 2019.
    17 changes: 17 additions & 0 deletions example.action-types.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,17 @@
    import { AsyncAction, AsyncFulfilledAction } from '.../redux-thunk-promise';

    export const FETCH = '.../FETCH';
    export const FETCH_PENDING = '.../FETCH_PENDING';
    export const FETCH_FULFILLED = '.../FETCH_FULFILLED';
    export const FETCH_REJECTED = '.../FETCH_REJECTED';

    export interface FetchAction extends AsyncAction<ApiResult> {
    type: typeof FETCH;
    }

    export type FetchFulfilledAction = AsyncFulfilledAction<
    FetchAction,
    typeof FETCH_FULFILLED
    >;

    export type FooAction = FetchAction | FetchFulfilledAction | ...;
    15 changes: 15 additions & 0 deletions example.actions.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,15 @@
    import { ThunkAction } from '.../redux-thunk-promise';
    import { AppState } from 'store/';
    import { FETCH, FetchAction } from './types';

    export const fetchFoo = (): ThunkAction<void, AppState, null, FetchAction> =>
    (dispatch, getState) => {
    if (...) {
    dispatch({
    type: FETCH,
    payload: api.list(), // `api.list` is `() => Promise<ApiResult>`
    }).then(({ value }) => {
    // value is ApiResult
    });
    }
    };
    52 changes: 52 additions & 0 deletions redux-thunk-promise.d.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,52 @@
    // https://github.com/pburtchaell/redux-promise-middleware/issues/253

    import { Action } from 'redux';
    import { AsyncAction as OrigAsyncAction } from 'redux-promise-middleware';
    import { ThunkDispatch as OrigThunkDispatch } from 'redux-thunk';

    // -----------------------------------
    // redux-promise-middleware extension
    // -----------------------------------

    declare type AsyncFunction<R = any> = () => Promise<R>;
    declare type AsyncPayload<R = any> =
    | Promise<R>
    | AsyncFunction<R>
    | {
    promise: Promise<R> | AsyncFunction<R>;
    data?: any;
    };

    export declare interface AsyncAction<R> extends OrigAsyncAction {
    payload?: AsyncPayload<R>;
    }

    type AsyncActionResult<A> = A extends AsyncAction<infer R> ? R : never;

    export type AsyncFulfilledAction<A extends AsyncAction, Type = string> = Omit<
    A,
    'type' | 'payload'
    > & {
    type: Type;
    payload: AsyncActionResult<A>;
    };

    type FulfilledDispatchResult<A extends AsyncAction> = {
    action: AsyncFulfilledAction<A>;
    value: AsyncActionResult<A>;
    };

    // ----------------------
    // redux-thunk extension
    // ----------------------

    export declare interface ThunkDispatch<S, E, A extends Action>
    extends OrigThunkDispatch<S, E, A> {
    <A extends AsyncAction>(asyncAction: A): Promise<FulfilledDispatchResult<A>>;
    }

    export declare type ThunkAction<R, S, E, A extends Action> = (
    dispatch: ThunkDispatch<S, E, A>,
    getState: () => S,
    extraArgument: E,
    ) => R;