Methods for using TypeScript in Zustand:
- Basic type definitions:
import { create } from 'zustand';
// Define types for state and actions
interface StoreState {
// State
count: number;
user: {
id: string;
name: string;
email: string;
} | null;
// Actions
increment: () => void;
decrement: () => void;
setUser: (user: StoreState['user']) => void;
reset: () => void;
}
// Create typed store
const useStore = create<StoreState>((set) => ({
// State
count: 0,
user: null,
// Actions
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
setUser: (user) => set({ user }),
reset: () => set({ count: 0, user: null }),
}));
- Type definitions with get:
import { create } from 'zustand';
interface StoreState {
count: number;
user: {
id: string;
name: string;
} | null;
increment: () => void;
incrementBy: (value: number) => void;
fetchUser: (userId: string) => Promise<void>;
}
const useStore = create<StoreState>((set, get) => ({
count: 0,
user: null,
increment: () => set((state) => ({ count: state.count + 1 })),
incrementBy: (value) => set((state) => ({ count: state.count + value })),
// Use get to access latest state
fetchUser: async (userId) => {
try {
const response = await fetch(`/api/users/${userId}`);
const userData = await response.json();
set({ user: userData });
// Use get to access latest state
console.log('Current count:', get().count);
} catch (error) {
console.error('Error fetching user:', error);
}
},
}));
- Type definitions with middleware:
import { create } from 'zustand';
import { persist, PersistOptions } from 'zustand/middleware';
interface StoreState {
count: number;
user: {
id: string;
name: string;
} | null;
increment: () => void;
setUser: (user: StoreState['user']) => void;
}
// Define type for persist middleware
type StorePersist = {
persist: {
clearStorage: () => void;
};
};
// Complete store type
type Store = StoreState & StorePersist;
// Persist config type
type PersistConfig = PersistOptions<StoreState, StorePersist>;
const useStore = create<Store>(
persist<StoreState, StorePersist>(
(set) => ({
count: 0,
user: null,
increment: () => set((state) => ({ count: state.count + 1 })),
setUser: (user) => set({ user }),
}),
{
name: 'my-storage',
} as PersistConfig
)
);
- Type definitions for selectors:
import { create } from 'zustand';
import { StoreState } from './store';
// In component
function Counter() {
// Type-safe selector
const count = useStore((state: StoreState) => state.count);
const increment = useStore((state: StoreState) => state.increment);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={increment}>Increment</button>
</div>
);
}
Key points:
- Use TypeScript interfaces to define types for state and actions
- Specify generic types in the create function
- Provide correct types for get and set functions
- When using middleware, properly define middleware types
- Ensure selector function return types match usage scenarios
- TypeScript helps catch type errors in state updates and usage