Last active
July 19, 2021 14:31
-
-
Save Vovan-VE/4be25aa16933e2df9cc0f8ce96ec7326 to your computer and use it in GitHub Desktop.
TypeScript: redux-thunk & redux-promise-middleware together
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Action } from 'redux'; | |
import { AsyncAction, AsyncFulfilledAction } from './redux-thunk-promise'; | |
import { ApiResult } from 'api/...'; | |
export const FETCH = '.../FETCH'; | |
export const FETCH_PENDING = '.../FETCH_PENDING'; | |
export const FETCH_FULFILLED = '.../FETCH_FULFILLED'; | |
export const FETCH_REJECTED = '.../FETCH_REJECTED'; | |
export type FetchAction = AsyncAction<typeof FETCH, ApiResult>; | |
export type FetchPendingAction = Action<typeof FETCH_PENDING>; | |
export type FetchDoneAction = Action<typeof FETCH_FULFILLED> & { | |
payload: ApiResult; | |
}; | |
export type FetchFailAction = Action<typeof FETCH_REJECTED> & { | |
payload: Error; | |
error: true; | |
}; | |
export type FooAction = | |
| FetchAction | |
| FetchPendingAction | |
| FetchDoneAction | |
| FetchFailAction; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { AppState, ThunkAction } from './example.store'; | |
import { FETCH, FetchAction } from './example.action-types'; | |
const fetch = (): FetchAction => ({ | |
type: FETCH, | |
payload: api.list(), // `api.list` is `() => Promise<ApiResult>` | |
}); | |
export const fetchFoo = (): ThunkAction<void> => | |
(dispatch, getState) => { | |
if (...) { | |
dispatch(fetch()).then(({ value }) => { | |
// value is ApiResult | |
}); | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ApiResult } from 'api/...'; | |
import { | |
FooAction, | |
FETCH_PENDING, | |
FETCH_FULFILLED, | |
FETCH_REJECTED, | |
} from './example.action-types.ts'; | |
export interface State { | |
data: ApiResult | null; | |
//... | |
} | |
const initialState: State = { | |
data: null, | |
//... | |
}; | |
export default (state = initialState, action: FooAction): State => { | |
switch (action.type) { | |
case FETCH_PENDING: | |
return { | |
...state, | |
//... | |
}; | |
case FETCH_FULFILLED: | |
return { | |
...state, | |
data: action.payload, | |
}; | |
case FETCH_REJECTED: | |
return { | |
...state, | |
//... | |
}; | |
default: | |
return state; | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Store } from 'redux'; | |
import { AppState } from 'state/reducer'; | |
import { | |
AppDispatch, | |
AsyncAction as _AsyncAction, | |
ThunkAction as _ThunkAction, | |
} from './redux-thunk-promise'; | |
export type AppStateStore = Store<AppState> & { | |
dispatch: AppDispatch<AppState, null>; | |
}; | |
export type AsyncAction<T, R> = _AsyncAction<T, R>; | |
export type ThunkAction<R> = _ThunkAction<R, AppState>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://github.com/pburtchaell/redux-promise-middleware/issues/253 | |
import { Action } from 'redux'; | |
// ================================== | |
// 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<T = any, R = any> extends Action<T> { | |
payload: AsyncPayload<R>; | |
} | |
type AsyncActionResult<A> = A extends AsyncAction<any, infer R> ? R : never; | |
export type AsyncFulfilledAction<A extends AsyncAction, T extends string = string> = Action<T> & { | |
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 | |
// ========================== | |
export type ThunkDispatchReturns<S, E, A> = A extends ThunkAction<infer R, S, E> ? R : A; | |
export declare type ThunkAction<R, S, E = null, D = AppDispatch<S, E>> = ( | |
dispatch: D, | |
getState: () => S, | |
extraArgument: E, | |
) => R; | |
// ========================= | |
export type AppDispatchResult<S, E, A> = AsyncDispatchReturns<ThunkDispatchReturns<S, E, A>>; | |
export interface AppDispatch<S, E> { | |
<T extends Action | ThunkAction<any, S, E>>(action: T): AppDispatchResult<S, E, T>; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment