Reducerify is a lightweight TypeScript library that simplifies the creation of reducers with full type inference. It helps you build type-safe reducers and automatically generates action creators, making state management more predictable and maintainable.
- Fully typed reducers: Get complete TypeScript type inference for your state and actions
- Automatic action creators: Generated action creators with proper payload typing
- Immutable by design: Encourages functional and declarative programming patterns
- Zero dependencies: Lightweight with no external dependencies
- Support for actions with and without payload: Flexible action handling
# Using pnpm
pnpm install reducerify
# Using bun
bun add reducerify
# Using npm
npm install reducerify
# Using yarn
yarn add reducerify
type TodoState = {
todos: Todo[];
newTodo: Todo
};
type Todo = {
name: string;
isClosed: boolean
};
import { forState, type ActionWithPayload } from "reducerify";
const { reducer, actions } = forState<TodoState>().createReducer({
// Action with payload
updateName: (state, action: ActionWithPayload<{ name: string }>) => {
return {
...state,
newTodo: {
...state.newTodo,
name: action.payload.name,
},
};
},
// Action without payload
save: (state) => {
return {
todos: [...state.todos, state.newTodo],
newTodo: { name: '', isClosed: false },
};
},
// Another action with payload
close: (state, action: ActionWithPayload<{ todoIndex: number }>) => {
return {
...state,
todos: state.todos.map((todo, index) =>
index === action.payload.todoIndex
? { ...todo, isClosed: true }
: todo
),
};
},
});
// Initial state
let state: TodoState = {
todos: [],
newTodo: { name: '', isClosed: false }
};
// Dispatch actions
state = reducer(state, actions.updateName({ name: 'Learn Reducerify' }));
state = reducer(state, actions.save());
state = reducer(state, actions.close({ todoIndex: 0 }));
The API to use immer is the same as the pure functional way, but you need to import forState
from reducerify/immer
.
import { forState } from "reducerify/immer";
const { reducer, actions } = forState<TodoState>().createImmerReducer({
update_name: (state, action: ActionWithPayload<{ name: string }>) => {
state.new_todo = {
...state.new_todo,
name: action.payload.name,
};
},
save: (state) => {
state.todos.push(state.new_todo);
state.new_todo = { name: '', is_closed: false };
},
close: (state, action: ActionWithPayload<{ todo_index: number }>) => {
state.todos = state.todos.map((todo, index) => {
if (index === action.payload.todo_index) {
return { ...todo, is_closed: true };
}
return todo;
});
},
});
Creates a reducer factory for a specific state type.
Creates a reducer and action creators from handler functions.
Returns an object with:
reducer
: The reducer function that handles state updatesactions
: Automatically generated action creators
ActionWithoutPayload
: Action without additional dataActionWithPayload<TPayload>
: Action with typed payload dataReducerHandlers<TState>
: Map of action types to handler functions
MIT © Frédéric Mascaro
See LICENSE for more information.