Skip to content

Instantly share code, notes, and snippets.

@mattpocock
Created June 21, 2019 14:20
Show Gist options
  • Save mattpocock/7a486e15ece507531ad1d0856e888280 to your computer and use it in GitHub Desktop.
Save mattpocock/7a486e15ece507531ad1d0856e888280 to your computer and use it in GitHub Desktop.
import { makeReducer, makeActionCreators } from './makeReducer';
const createReducer = <
State,
Actions extends { [K in keyof Actions]: (payload?: any) => void }
>({
initialState,
actions,
}: Params<State, Actions>): CreateReducerReturnedObject<State, Actions> => {
const reducer = makeReducer({
initialState,
actions,
});
const actionCreators = makeActionCreators({ actions });
return {
// @ts-ignore
constants: Object.keys(actions).reduce(
(object, key) => ({ ...object, [key]: key }),
{}
),
reducer,
// @ts-ignore
actions: actionCreators,
};
};
interface Params<
State,
Actions extends { [K in keyof Actions]: (payload?: any) => void }
> {
initialState: State;
actions: ActionDefinition<State, Actions>;
}
interface CreateReducerReturnedObject<
State,
Actions extends { [K in keyof Actions]: (payload?: any) => void }
> {
constants: {
[K in keyof Actions]: K;
};
reducer: (
state: State,
action: {
type: keyof Actions;
payload?: Parameters<Actions[keyof Actions]>[0];
}
) => State;
actions: {
[K in keyof Actions]: (...args: Parameters<Actions[K]>) => {
type: string;
payload?: Parameters<Actions[K]>[0]
}
};
}
type ActionDefinition<
State,
Actions extends { [K in keyof Actions]: (payload?: any) => void }
> = {
[K in keyof Actions]: (
state: State,
payload: Parameters<Actions[K]>[0]
) => State;
};
const { constants, reducer, actions } = createReducer<State, Actions>({
initialState: {
isOpen: false,
},
actions: {
changeModalState: (state, isOpen) => ({
...state,
isOpen,
}),
},
});
const createdAction = actions.changeModalState(true)
interface State {
isOpen: boolean;
}
interface Actions {
changeModalState: (newState: boolean) => void;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment