Repository: pmndrs/zustand
File: src/middleware.ts (TypeScript)

Code before:
    initialState: PrimaryState,
    create: (
      // Note: NamedSet added for convenience
      set: SetState<PrimaryState> & NamedSet<PrimaryState>,
      get: GetState<PrimaryState>,
      api: StoreApi<PrimaryState>
    ) => SecondaryState
  ) =>
  (
    set: SetState<Combine<PrimaryState, SecondaryState>>,
    get: GetState<Combine<PrimaryState, SecondaryState>>,
    api: StoreApi<Combine<PrimaryState, SecondaryState>>
  ) =>
    Object.assign(
      {},
      initialState,
      create(set as any, get as any, api as any)
    ) as Combine<PrimaryState, SecondaryState>

type DeepPartial<T extends Object> = {
  [P in keyof T]?: DeepPartial<T[P]>
}
export type StateStorage = {
  getItem: (name: string) => string | null | Promise<string | null>
  setItem: (name: string, value: string) => void | Promise<void>
  removeItem: (name: string) => void | Promise<void>
}
type StorageValue<S> = { state: DeepPartial<S>; version?: number }
export type PersistOptions<
  S,
  PersistedState extends Partial<S> = Partial<S>
> = {
  /** Name of the storage (must be unique) */
  name: string
  /**
   * A function returning a storage.
   * The storage must fit `window.localStorage`'s api (or an async version of it).
   * For example the storage could be `AsyncStorage` from React Native.
   *
   * @default () => localStorage
   */
  getStorage?: () => StateStorage
  /**
   * Use a custom serializer.
   * The returned string will be stored in the storage.
   *
   * @default JSON.stringify
   */
  serialize?: (state: StorageValue<S>) => string | Promise<string>
  /**
   * Use a custom deserializer.

Review comment (suggestion):
@dai-shi FYI for the changelog: `persist` now require a storage with a `removeItem` method. That's kind of a breaking change, especially if the user gives a custom storage.

Code after:
    create: (
      // Note: NamedSet added for convenience
      set: SetState<PrimaryState> & NamedSet<PrimaryState>,
      get: GetState<PrimaryState>,
      api: StoreApi<PrimaryState>
    ) => SecondaryState
  ) =>
  (
    set: SetState<Combine<PrimaryState, SecondaryState>>,
    get: GetState<Combine<PrimaryState, SecondaryState>>,
    api: StoreApi<Combine<PrimaryState, SecondaryState>>
  ) =>
    Object.assign(
      {},
      initialState,
      create(set as any, get as any, api as any)
    ) as Combine<PrimaryState, SecondaryState>

type DeepPartial<T extends Object> = {
  [P in keyof T]?: DeepPartial<T[P]>
}
export type StateStorage = {
  getItem: (name: string) => string | null | Promise<string | null>
  setItem: (name: string, value: string) => void | Promise<void>
  // Note: This will be required in v4
  removeItem?: (name: string) => void | Promise<void>
}
type StorageValue<S> = { state: DeepPartial<S>; version?: number }
export type PersistOptions<
  S,
  PersistedState extends Partial<S> = Partial<S>
> = {
  /** Name of the storage (must be unique) */
  name: string
  /**
   * A function returning a storage.
   * The storage must fit `window.localStorage`'s api (or an async version of it).
   * For example the storage could be `AsyncStorage` from React Native.
   *
   * @default () => localStorage
   */
  getStorage?: () => StateStorage
  /**
   * Use a custom serializer.
   * The returned string will be stored in the storage.
   *
   * @default JSON.stringify
   */
  serialize?: (state: StorageValue<S>) => string | Promise<string>
  /**
   * Use a custom deserializer.