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.
TypeScript: redux-thunk & redux-promise-middleware together
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 | ...;
import { ThunkAction } from '.../redux-thunk-promise';
import { AppState } from 'store/';
import { FETCH, FetchAction } from './types';
export const fetchFoo = (): ThunkAction<void, AppState> =>
(dispatch, getState) => {
if (...) {
dispatch({
type: FETCH,
payload: api.list(), // `api.list` is `() => Promise<ApiResult>`
}).then(({ value }) => {
// value is ApiResult
});
}
};
// https://github.com/pburtchaell/redux-promise-middleware/issues/253
import { AsyncAction as OrigAsyncAction } from 'redux-promise-middleware';
// -----------------------------------
// 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 = any> extends OrigAsyncAction {
payload: AsyncPayload<R>;
}
type AsyncActionResult<A> = A extends AsyncAction<infer R> ? R : never;
export type AsyncFulfilledAction<
A extends AsyncAction,
Type extends string = string
> = Omit<A, 'type' | 'payload'> & {
type: Type;
payload: AsyncActionResult<A>;
};
type FulfilledDispatchResult<A extends AsyncAction> = {
action: AsyncFulfilledAction<A>;
value: AsyncActionResult<A>;
};
export type AsyncDispatchReturns<T> = T extends AsyncAction
? Promise<FulfilledDispatchResult<T>>
: T;
// ----------------------
// redux-thunk extension
// ----------------------
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 = null> = (
dispatch: ThunkDispatch<S, E>,
getState: () => S,
extraArgument: E,
) => R;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment