Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/marckassay/zustand-redux-extends-type

A zustand redux extended type for actions
https://github.com/marckassay/zustand-redux-extends-type

redux typescript typings zustand

Last synced: about 1 month ago
JSON representation

A zustand redux extended type for actions

Awesome Lists containing this project

README

        

# zustand-redux-extends-type

To be used with [zustand's redux middleware](https://github.com/pmndrs/zustand/blob/main/docs/guides/flux-inspired-practice.md). To install:

```
npm add zustand-redux-extends-type -D # or yarn add zustand-redux-extends-type -D
```

Leveraging typings (`ReduxExtends` and `FeatureEventActions`) as below eliminates the need to use any type assertions in reducers. It also enforces only valid values for properties when `dispatch` is being typed out.

```typescript
import type { ReduxExtends } from "zustand-redux-extends-type";

type FeatureEventActions = {
grumpiness: {
increase: number;
decrease: number;
reset: undefined;
};
happiness: {
"show all": User[];
level: "low" | "sort of" | "high";
};
};

const useGrumpyStore = create(
redux(
(
state: { count: number; level: "low" | "sort of" | "high" },
{ type, payload }: ReduxExtends
) => {
switch (type) {
case "grumpiness/increase":
return { ...state, count: state.count + payload };
case "grumpiness/decrease":
return { ...state, count: state.count - payload };
case "grumpiness/reset":
return { ...state, count: 0 };
//removed happiness cases for brevity
default:
return state;
}
},
{ count: 0, level: "high" }
)
);

const dispatch = useGrumpyStore((state) => state.dispatch);
dispatch({ type: "grumpiness/decrease", payload: 1 });
```

The structure of this map type, `FeatureEventActions`, is premised on [Redux's recommendation for actions](https://redux.js.org/tutorials/fundamentals/part-3-state-actions-reducers#what-youve-learned):

"_The type field should be a readable string, and is usually written as 'feature/eventName'_"

For this example, 'grumpiness' and 'happiness' are features with event names of 'increase' and 'show all' respectively. Each event name is typed for what will be its `payload` type. Any `action` object of `ReduxExtends`, either as a parameter of `reducer` or `dispatch`, has its `type` property constrained to what will be parsed by TypeScript. This will also dictate the `payload` type.