The only breaking changes in v4 are in types. If you are using Zustand with TypeScript or JSDoc type annotations, this guide applies. Otherwise, no migration is required.
create
Applicable imports:
Using leaf middleware (combine or redux)
If you are using a “leaf” middleware like
combine or redux, remove all type parameters from create.StateCreator
Applicable imports:
If you are using
StateCreator, you are likely authoring a middleware or using the “slices” pattern. Check the TypeScript Guide for more information on authoring middlewares and the slices pattern.PartialState
Applicable imports:
Enable exactOptionalPropertyTypes
Enable
exactOptionalPropertyTypes in your tsconfig.json:We’re no longer using the trick to disallow
{ foo: undefined } to be assigned to Partial<{ foo: string }>. Instead, we’re relying on the exactOptionalPropertyTypes TypeScript option.useStore
Applicable imports:
No type parameters
If you are not passing any type parameters to
useStore, no migration is required.UseBoundStore
Applicable imports:
UseBoundStore<T> with UseBoundStore<StoreApi<T>>, and UseBoundStore<T, S> with UseBoundStore<S>.
UseContextStore
Applicable imports:
createContext
Applicable imports:
createContext<T>() with createContext<StoreApi<T>>(), and createContext<T, S>() with createContext<S>().
Middleware: combine, devtools, subscribeWithSelector
Applicable imports:
If you are not passing any type parameters to
combine, devtools, or subscribeWithSelector, no migration is required.If you are, remove all the type parameters, as they are inferred automatically.Middleware: persist
Applicable imports:
Remove type parameters
If you are passing any type parameters, remove them as they are inferred automatically.
Check if you're using partialize option
If you are passing the
partialize option, no further steps are required for migration.Handle compilation errors (if any)
If you see compilation errors, you have to find and fix the errors yourself, as they might indicate unsound code.Workaround: Pass
s => s as Partial<typeof s> to partialize. If your partialized state is truly Partial<T>, you should not encounter any bugs.The runtime behavior has not changed, only the types are now correct.
Middleware: redux
Applicable imports:
redux, no migration is required.
If you are, remove all the type parameters and annotate only the second (action) parameter: