🧸
zfy
  • Getting started
  • 🤓Guides
    • Creating & using a store
    • Persisting & rehydrating data
    • Using middlewares
    • Handling multiple stores
    • Type checking with TypeScript
  • 📚API reference
    • Types
      • CreateStoreType
      • CreateStoreConfigType
      • CreateStoreOptionsType
      • StoreType
      • ZfyMiddlewareType
      • InitStoresType
      • InitStoresResetOptionsType
    • createStore
    • initStores
    • PersistGate
    • useRehydrate
  • 🗃️Others
    • Help
    • Contributing
    • Changelog
    • GitHub
Powered by GitBook
On this page
  • API reference
  • persist
  • subscribeWithSelector

Was this helpful?

  1. API reference
  2. Types

CreateStoreType

PreviousTypesNextCreateStoreConfigType

Last updated 3 years ago

Was this helpful?

Interface representing the data structure of themethod's output.

src/types.ts
import type { UseBoundStore } from 'zustand'
 import type {
  StoreApiWithPersist,
  StoreApiWithSubscribeWithSelector,
} from 'zustand/middleware'

type CreateStoreType<StoreDataType> = UseBoundStore<
  StoreType<StoreDataType>
> & {
  persist?: StoreApiWithPersist<StoreType<StoreDataType>>['persist']
  subscribeWithSelector?: StoreApiWithSubscribeWithSelector<
    StoreType<StoreDataType>
  >['subscribe']
}

API reference

persist

persist?: StoreApiWithPersist<StoreType<StoreDataType>>['persist']

The detailed API reference is available here:

subscribeWithSelector

subscribeWithSelector?: StoreApiWithSubscribeWithSelector<
  StoreType<StoreDataType>
>['subscribe']

The detailed API reference is available here:

The following elements are provided on top of the regular ones returned by.

Only provided if you've enabled themiddleware.

Only provided if you've enabled themiddleware.

It uses the exact same API as the new middleware introduced with zustand . The only difference is that zfy allows you to plug it in by simply adding a boolean to 3rd (options) argument.

📚
zustand's createStore()
createStore()
subscribeWithSelector()
3.6.0
persist
subscribe
createStore()
https://github.com/pmndrs/zustand/wiki/Persisting-the-store's-data#api
https://github.com/pmndrs/zustand/blob/main/src/middleware/subscribeWithSelector.ts
import type { StateCreator, StoreMutatorIdentifier } from '../vanilla.ts'

type SubscribeWithSelector = <
  T,
  Mps extends [StoreMutatorIdentifier, unknown][] = [],
  Mcs extends [StoreMutatorIdentifier, unknown][] = [],
>(
  initializer: StateCreator<
    T,
    [...Mps, ['zustand/subscribeWithSelector', never]],
    Mcs
  >,
) => StateCreator<T, Mps, [['zustand/subscribeWithSelector', never], ...Mcs]>

type Write<T, U> = Omit<T, keyof U> & U

type WithSelectorSubscribe<S> = S extends { getState: () => infer T }
  ? Write<S, StoreSubscribeWithSelector<T>>
  : never

declare module '../vanilla' {
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  interface StoreMutators<S, A> {
    ['zustand/subscribeWithSelector']: WithSelectorSubscribe<S>
  }
}

type StoreSubscribeWithSelector<T> = {
  subscribe: {
    (listener: (selectedState: T, previousSelectedState: T) => void): () => void
    <U>(
      selector: (state: T) => U,
      listener: (selectedState: U, previousSelectedState: U) => void,
      options?: {
        equalityFn?: (a: U, b: U) => boolean
        fireImmediately?: boolean
      },
    ): () => void
  }
}

type SubscribeWithSelectorImpl = <T extends object>(
  storeInitializer: StateCreator<T, [], []>,
) => StateCreator<T, [], []>

const subscribeWithSelectorImpl: SubscribeWithSelectorImpl =
  (fn) => (set, get, api) => {
    type S = ReturnType<typeof fn>
    type Listener = (state: S, previousState: S) => void
    const origSubscribe = api.subscribe as (listener: Listener) => () => void
    api.subscribe = ((selector: any, optListener: any, options: any) => {
      let listener: Listener = selector // if no selector
      if (optListener) {
        const equalityFn = options?.equalityFn || Object.is
        let currentSlice = selector(api.getState())
        listener = (state) => {
          const nextSlice = selector(state)
          if (!equalityFn(currentSlice, nextSlice)) {
            const previousSlice = currentSlice
            optListener((currentSlice = nextSlice), previousSlice)
          }
        }
        if (options?.fireImmediately) {
          optListener(currentSlice, currentSlice)
        }
      }
      return origSubscribe(listener)
    }) as any
    const initialState = fn(set, get, api)
    return initialState
  }
export const subscribeWithSelector =
  subscribeWithSelectorImpl as unknown as SubscribeWithSelector
https://github.com/colorfy-software/zfy/blob/main/src/types.ts#L23-L30
import type {
  State,
  GetState,
  SetState,
  StoreApi,
  StateCreator,
  UseBoundStore,
  EqualityChecker,
} from 'zustand'
import type {
  PersistOptions,
  StoreApiWithPersist,
  StoreApiWithSubscribeWithSelector,
} from 'zustand/middleware'

export interface StoreType<StoreDataType> extends State {
  name: string
  data: StoreDataType
  reset: () => void
  update: (producer: (data: StoreDataType) => void) => void
}

export type CreateStoreType<StoreDataType> = UseBoundStore<
  StoreType<StoreDataType>
> & {
  persist?: StoreApiWithPersist<StoreType<StoreDataType>>['persist']
  subscribeWithSelector?: StoreApiWithSubscribeWithSelector<
    StoreType<StoreDataType>
  >['subscribe']
}

export type CreateStoreConfigType<
  StoreDataType,
  StoreApiType extends StoreApi<StoreType<StoreDataType>> = StoreApi<
    StoreType<StoreDataType>
  >
> = StateCreator<
  StoreType<StoreDataType>,
  SetState<StoreType<StoreDataType>>,
  GetState<StoreType<StoreDataType>>,
  StoreApiType
>

export interface CreateStoreOptionsType<StoreDataType> {
  log?: boolean
  subscribe?: boolean
  persist?: Omit<
    PersistOptions<StoreType<StoreDataType>>,
    'name' | 'blacklist' | 'whitelist'
  > & {
    name?: string
    getStorage: Exclude<
      PersistOptions<StoreType<StoreDataType>>['getStorage'],
      undefined
    >
  }
  customMiddlewares?: ZfyMiddlewareType<StoreDataType>[]
}

export type ZfyMiddlewareType<
  StoreDataType,
  StoreApiType extends StoreApi<StoreType<StoreDataType>> = StoreApi<
    StoreType<StoreDataType>
  >
> = (
  storeName: string,
  config: CreateStoreConfigType<StoreDataType>,
  options?: CreateStoreOptionsType<StoreDataType>
) => CreateStoreConfigType<StoreDataType, StoreApiType>

export type InitStoresResetOptionsType<StoreDataType> = {
  omit?: Array<keyof StoreDataType>
}

export type InitStoresType<StoresDataType> = {
  stores: {
    [StoreNameType in keyof StoresDataType]: CreateStoreType<
      StoresDataType[StoreNameType]
    >
  } & {
    rehydrate: () => Promise<boolean>
    reset: (options?: InitStoresResetOptionsType<StoresDataType>) => void
  }
  useStores: <StoreNameType extends keyof StoresDataType, Output>(
    storeName: StoreNameType,
    selector: (data: StoresDataType[StoreNameType]) => Output,
    equalityFn?: EqualityChecker<Output>
  ) => Output
}