Zustand v4+ dùng curried create với generic create<StoreType>() — thiếu dấu () thứ hai TypeScript sẽ không infer đúng.
- Pattern chuẩn với TypeScript: định nghĩa type cho toàn bộ store trước, rồi pass vào generic.
- Zustand v4+ dùng curried create:
create<StoreType>()((set, get) => ({...}))— dấu()thứ hai bắt buộc để TypeScript infer đúng.
Ví dụ: interface CartStore { items: CartItem[]; total: number; addItem: (item: CartItem) => void; clearCart: () => void } → const useCartStore = create<CartStore>()((set, get) => ({ items: [], total: 0, addItem: (item) => set(s => ({ items: [...s.items, item], total: s.total + item.price })), clearCart: () => set({ items: [], total: 0 }) })).
Zustand v4+ uses curried create with generic create<StoreType>() — missing the second () means TypeScript cannot infer types correctly.
- Standard TypeScript pattern: define the type for the entire store first, then pass it as a generic.
- Zustand v4+ uses curried create:
create<StoreType>()((set, get) => ({...}))— the second()is required for TypeScript to infer types correctly. - Example:
interface CartStore { items: CartItem[]; total: number; addItem: (item: CartItem) => void; clearCart: () => void }→const useCartStore = create<CartStore>()((set, get) => ({ items: [], total: 0, addItem: (item) => set(s => ({ items: [...s.items, item], total: s.total + item.price })), clearCart: () => set({ items: [], total: 0 }) })). - For slices use the
StateCreatortype:type CartSlice = { items: CartItem[]; addItem: (item: CartItem) => void }; const createCartSlice: StateCreator<BoundStore, [], [], CartSlice> = (set) => ({...}). - Infer store type from the store itself:
type StoreState = ReturnType<typeof useStore.getState>.
Pitfall: using create without a generic loses type safety and set accepts any.