Skip to content

Instantly share code, notes, and snippets.

@wuzzeb
Created September 29, 2019 19:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wuzzeb/d4d1cb76eeba56c10919356d5c4bf8e0 to your computer and use it in GitHub Desktop.
Save wuzzeb/d4d1cb76eeba56c10919356d5c4bf8e0 to your computer and use it in GitHub Desktop.
Example typed redux middleware
export enum PledgeStatus {
Starting = "Pledge_Starting",
Completed = "Pledge_Completed",
Error = "Pledge_Error"
}
export type Pledge<T> =
| { status: PledgeStatus.Starting }
| { status: PledgeStatus.Completed; result: T }
| { status: PledgeStatus.Error; error: Error };
export type PledgeToPromise<AP> = {
[P in keyof AP]: "pledge" extends P ? (AP[P] extends Pledge<infer R> ? Promise<R> : AP[P]) : AP[P];
};
interface WithPromise<R> {
pledge: Promise<R>;
}
// tslint:disable-next-line:no-any
function hasPledge<R>(obj: any): obj is WithPromise<R> {
return "pledge" in obj && obj.pledge && obj.pledge instanceof Promise;
}
export function pledgeMiddleware<A>(dispatch: (a: A) => void): (action: PledgeToPromise<A>) => void {
return action => {
if (hasPledge(action)) {
// tslint:disable-next-line:no-any
const anyAction: any = action;
dispatch({ ...anyAction, pledge: { status: PledgeStatus.Starting } });
action.pledge
.then(r => {
dispatch({
...anyAction,
pledge: { status: PledgeStatus.Completed, result: r }
});
})
.catch((e: Error) => {
dispatch({
...anyAction,
pledge: { status: PledgeStatus.Error, error: e }
});
});
} else {
// tslint:disable-next-line:no-any
return dispatch(action as any);
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment