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

Code before:
   */
  blacklist?: (keyof S)[]
  /**
   * Only store the listed properties.
   */
  whitelist?: (keyof S)[]
  /**
   * A function returning another (optional) function.
   * The main function will be called before the state rehydration.
   * The returned function will be called after the state rehydration or when an error occurred.
   */
  onRehydrateStorage?: (state: S) => ((state?: S, error?: Error) => void) | void
  /**
   * If the stored state's version mismatch the one specified here, the storage will not be used.
   * This is useful when adding a breaking change to your store.
   */
  version?: number
  /**
   * A function to perform persisted state migration.
   * This function will be called when persisted state versions mismatch with the one specified here.
   */
  migrate?: (persistedState: any, version: number) => S | Promise<S>
}
interface Thenable<Value> {
  then<V>(onFulfilled: (value: Value) => V): Thenable<V>
  catch<V>(onRejected: (value: Error) => V): Thenable<V>
}

const toThenable = <Result, Input>(
  fn: (input: Input) => Result | Promise<Result> | Thenable<Result>
) => (input: Input): Thenable<Result> => {
  try {
    const result = fn(input)
    if (result instanceof Promise) {
      return result as Thenable<Result>
    }
    return {
      then(onFulfilled) {
        return toThenable(onFulfilled)(result as Result)
      },
      catch(onRejected) {
        return this as Thenable<any> // FIXME can we avoid any ?
      },
    }
  } catch (e) {
    return {
      then(onFulfilled) {
        return this as Thenable<any> // FIXME can we avoid any ?
      },
      catch(onRejected) {
        return toThenable(onRejected)(e)

Review comment (suggestion):
```suggestion
  catch<V>(onRejected: (reason: Error) => V): Thenable<V>
```

Code after:
   * @default JSON.parse
   */
  deserialize?: (str: string) => StorageValue<S> | Promise<StorageValue<S>>
  /**
   * Prevent some items from being stored.
   */
  blacklist?: (keyof S)[]
  /**
   * Only store the listed properties.
   */
  whitelist?: (keyof S)[]
  /**
   * A function returning another (optional) function.
   * The main function will be called before the state rehydration.
   * The returned function will be called after the state rehydration or when an error occurred.
   */
  onRehydrateStorage?: (state: S) => ((state?: S, error?: Error) => void) | void
  /**
   * If the stored state's version mismatch the one specified here, the storage will not be used.
   * This is useful when adding a breaking change to your store.
   */
  version?: number
  /**
   * A function to perform persisted state migration.
   * This function will be called when persisted state versions mismatch with the one specified here.
   */
  migrate?: (persistedState: any, version: number) => S | Promise<S>
}

interface Thenable<Value> {
  then<V>(
    onFulfilled: (value: Value) => V | Promise<V> | Thenable<V>
  ): Thenable<V>
  catch<V>(
    onRejected: (reason: Error) => V | Promise<V> | Thenable<V>
  ): Thenable<V>
}

const toThenable = <Result, Input>(
  fn: (input: Input) => Result | Promise<Result> | Thenable<Result>
) => (input: Input): Thenable<Result> => {
  try {
    const result = fn(input)
    if (result instanceof Promise) {
      return result as Thenable<Result>
    }
    return {
      then(onFulfilled) {
        return toThenable(onFulfilled)(result as Result)
      },
      catch(_onRejected) {