Before:
interface BearState {
bears: number
increase: (by: number) => void
}
const useBearStore = create<BearState>()((set) => ({
bears: 0,
increase: (by) => set((state) => ({ bears: state.bears + by })),
}))
Now:
const initialState = { bears: 0 }
export type BearState = typeof initialState
export const useBearStore = create<BearState>()(() => initialState)
export const bearActions = {
increase(by: number) {
useBearStore.setState((state) => ({ bears: state.bears + by }))
},
}
What if the fields in initialState are null, undefined, union types, or string? We can use TypeScript’s as syntax to fix this issue and avoid rewriting the store’s type. For example:
const initialState = {
bears: 0,
gender: 1 as 0 | 1 | 2 | undefined,
};
export type BearState = typeof initialState;
✨ Why it’s better?
1.No need to manually define and sync the interface
2.Actions are separated and can grow freely
3.typeof initialState automatically infers the correct types
4.Cleaner, easier to maintain, and still fully typed
Top comments (1)
No more write types for actions!