-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TypeScript type conflict with persist middleware #650
Comments
Thanks for reporting. const useAuthStore = create<AuthStore>(
persist(
(set) => ({
token: undefined,
authenticated: false,
authenticate: async (username, password) => {
set({authenticated: true})
},
}),
{ name: "auth-store" }
)
); If you need a custom store api type, it's a bit tricker. see #632 and: zustand/tests/middlewareTypes.test.tsx Line 573 in 21a28ff
|
Hey @dai-shi I tried the solution you posted, but I still run into the type problem. The problem just came up for me when I upgrade from |
Thanks for chiming in. Hmm, I thought I tested in tests. As you say, it can repro in csb: 🤔 🤔 🤔 |
I nailed down the issue in typescript playground. |
Here's another workaround: type MyState = {
token: string | undefined
authenticated: boolean
authenticate: (username: string, password: string) => Promise<void>
}
type MyPersist = (
config: StateCreator<MyState>,
options: PersistOptions<MyState>
) => StateCreator<MyState>
const useStore = create<MyState>(
(persist as MyPersist)(
(set) => ({
token: undefined,
authenticated: false,
authenticate: async (_username, _password) => {
set({ authenticated: true })
},
}),
{ name: 'auth-store' }
)
) Basically, we type cast to that of v3.6.2 which didn't have persist api. |
Thank you @dai-shi I like that workaround |
Any workaround for the |
I think I tried to cover various patterns in middlewareTypes.test.tsx for workarounds. What's a missing combination? |
Here a pattern of store that uses a normal store slice + a persist store slice in TypeScript in case this is helpful for somebody. I struggled to get the type rights in order to be able to use the store via the vanilla API ( import { createConfigurationStoreSlice } from "./configuration/store";
import { createWalletStoreSlice } from "./wallet/store";
// A Store slice can read its state and the state of other slices but can only set its own state
export type StoreSlice<T extends object, E extends object = T> = (
set: SetState<T>,
get: GetState<E extends T ? E : E & T>
) => T;
type PersistStoreApiType = ReturnType<typeof createWalletStoreSlice>;
const createRootSlice = (
set: SetState<any>,
get: GetState<any>,
api: Mutate<
StoreApi<PersistStoreApiType>,
[["zustand/persist", Partial<PersistStoreApiType>]]
>
) => {
return {
...createConfigurationStoreSlice(set, get),
...persist(createWalletStoreSlice, {
name: "wallet",
partialize: (state) => {
return {
lastConnectedWalletLabel: state.lastConnectedWalletLabel,
};
},
})(set, get, api),
};
};
export const useStore = create(createRootSlice); If you have any other store slice that you want to persist, you can add it to the type PersistStoreApiType =
ReturnType<typeof createFirstStoreSlice> &
ReturnType<typeof createSecondStoreSlice> &
ReturnType<typeof createThirdStoreSlice>; |
Expanding on this one, this version allows you to access the type MyState = {
token: string | undefined
authenticated: boolean
authenticate: (username: string, password: string) => Promise<void>
}
type PersistResult<
T = MyState,
U = Partial<MyState>,
Mps extends [StoreMutatorIdentifier, unknown][] = [],
Mcs extends [StoreMutatorIdentifier, unknown][] = [],
> = StateCreator<T, Mps, [['zustand/persist', U], ...Mcs]>
type MyPersist = (
config: StateCreator<MyState>,
options: PersistOptions<Partial<MyState>>,
) => MyPersist
const useStore = create<MyState>(
(persist as MyPersist)(
(set) => ({
token: undefined,
authenticated: false,
authenticate: async (_username, _password) => {
set({ authenticated: true })
},
}),
{ name: 'auth-store' }
)
) |
Life saver! There was no way I could fix the following error message without (Excuse the application specific types in the error message below. There's nothing sensitive about such types—we're just coding a sort of game about immigration—so I won't bother removing them. Just in case anyone encounters a similar error with a similar pattern. It called my attention that many of my types showed up as
|
Thanks for the workaround! For anyone having an issue with the type MyState = {
token: string | undefined
authenticated: boolean
authenticate: (username: string, password: string) => Promise<void>
}
type MyPersist = (
config: StateCreator<MyState>,
options: PersistOptions<MyState, Partial<MyState>>
) => StateCreator<MyState>
const useStore = create<MyState>(
(persist as MyPersist)(
(set) => ({
token: undefined,
authenticated: false,
authenticate: async (_username, _password) => {
set({ authenticated: true })
},
}),
{ name: 'auth-store' }
)
) |
I prefer to use |
Hi there @dai-shi, thank you!! Your solution helped me ✨ |
Looks like this issue is old. I think typing is fixed/improved since then. Please open a new discussion with typescript playground reproduction. |
I'm so sorry for wasting your time, I used TypeScript without adding the extra parenthesis :( I should've read the docs :) https://docs.pmnd.rs/zustand/guides/typescript
|
I am unable to get the
persist
middleware working with TypeScript if I define state properties with multiple types or with theboolean
type.zustand version: 3.6.4
TypeScript version: 4.1.3
Example code:
persist
function gives the following errors:Everything works as expected if I just define
token
andauthenticated
asany
type.The text was updated successfully, but these errors were encountered: