codez.guru

On this Page

  • Typing a Zustand Store with Generics
  • How to Use z.infer-like Patterns
  • Avoiding Over-Annotation
  • Reusing Store Types in Components

On this Guide

  • Lesson 01: Introduction to Zustand and Store Basics
  • Lesson 02: Creating Your First Store with TypeScript
  • Lesson 03: Reading and Updating State in React Components
  • Lesson 04: Selectors and Optimizing Renders
  • Lesson 05: Handling Booleans, Counters, and Simple Objects
  • Lesson 06: Derived State and Computed Values
  • Lesson 07: Type Inference and Store Typing Best Practices
  • Lesson 08: Custom Hooks and Reusable State Accessors

Typing a Zustand Store with Generics

Zustand’s create() accepts a generic type that represents your full store shape:

type CounterStore = {
  count: number;
  inc: () => void;
};

const useCounterStore = create<counterstore>((set) =&gt; ({
  count: 0,
  inc: () =&gt; set((s) =&gt; ({ count: s.count + 1 })),
}));

βœ… This gives you autocomplete, type checking, and error safety across your app.


How to Use typeof for Inference

Instead of repeating types, infer from the store itself:

const useUserStore = create&lt;{
  name: string;
  setName: (name: string) =&gt; void;
}&gt;((set) =&gt; ({
  name: "",
  setName: (name) =&gt; set({ name }),
}));

export type UserStore = ReturnType<typeof useuserstore>;

This gives you access to the shape of your store anywhere else in your app.


Avoiding Over-Annotation

You don’t need to overtype every state update.

❌ Too much:

set((state: CounterStore) =&gt; ({ count: state.count + 1 }));

βœ… Just let TypeScript infer:

set((s) =&gt; ({ count: s.count + 1 }));

Reusing Store Types in Components

Export your store’s type if it helps with testing or props:

export type CounterStore = {
  count: number;
  inc: () =&gt; void;
};

Then use it elsewhere:

const MyButton: FC&lt;{ store: CounterStore }&gt; = ({ store }) =&gt; (
  <button onclick="{store.inc}">Click</button>
);

Summary

  • Always use <t> with create() to ensure type-safe stores
  • Use ReturnType<typeof usestore> to infer full types
  • Don’t over-annotate β€” let TS infer where possible
  • Export your store types for maximum reuse

Next: Lesson 08 – Custom Hooks and Reusable State Accessors