Skip to content

Instantly share code, notes, and snippets.

@ianldgs
Created June 22, 2021 11:40
Show Gist options
  • Save ianldgs/726fa09def9d240c9ba6d10495ce7b56 to your computer and use it in GitHub Desktop.
Save ianldgs/726fa09def9d240c9ba6d10495ce7b56 to your computer and use it in GitHub Desktop.
/**
* Type used to declare a type-safe reducer without switch-cases.
*
* @example
* ```ts
* interface State {
* loading: boolean;
* }
*
* type Action = Readonly<
* | { type: 'setLoading'; payload: boolean }
* | { type: 'doSomething'; payload: any }
* >;
*
* export const actions: ActionsCreator<Action, State> = (state) => ({
* // the `payload` argument already has the correct type (`boolean`)
* // and the method is already expected to return a `State`.
* setLoading(payload) {
* return {
* ...state,
* loading,
* }
* },
*
* // will throw a compilation error if all actions are not implemented
* // like in this example, `doSomething` is missing
* });
*
* export const reducer = (state: Model, { type, payload }: Action): Model => {
* // @ts-ignore
* return actions(state)[type]?.(payload) || state;
* };
* ```
*/
export type ActionsCreator<T extends { type: string; payload?: any }, S = any> = (
state: S,
) => {
[K in T['type']]: (action: Extract<T, { type: K }>['payload']) => S;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment