Skip to content

Instantly share code, notes, and snippets.

@Willmo36
Created June 26, 2021 18:06
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 Willmo36/46fb1163087ea5dc142f71e114ec2f3e to your computer and use it in GitHub Desktop.
Save Willmo36/46fb1163087ea5dc142f71e114ec2f3e to your computer and use it in GitHub Desktop.
Reducer helper functions
export type Action = { type: string };
export type Reducer<S, A extends Action> = (state: S, action: A) => S;
export type ReducerByAction<S, A extends Action> = A extends any
? Partial<Record<A["type"], Reducer<S, A>>>
: never;
export type ReducerByKey<S, A extends Action> = Partial<{
[SK in keyof S]: Reducer<S[SK], A>
}>;
export const reducerByAction = <S, A extends Action>(
handlers: ReducerByAction<S, A>
): Reducer<S, A> => (state, action) => {
const handler: Reducer<S, A> = handlers[action.type] ?? identity;
return handler(state, action);
};
export const reducerByKey = <S, A extends Action>(
handlers: ReducerByKey<S, A>
): Reducer<S, A> => {
const keys = Object.keys(handlers) as (keyof S)[];
return (state, action) => {
return keys.reduce((s, k) => {
const skReducer = handlers[k]!;
const sk = skReducer(s[k], action);
return { ...s, [k]: sk };
}, state);
};
};
// Example
type S = { foo: { bar: number } };
type A = { type: "inc" };
reducerByKey<S, A>({
foo: reducerByKey({
bar: reducerByAction({
inc: (bar, inc) => bar + 1
})
})
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment