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

Code before:
import { useEffect, useLayoutEffect, useReducer, useRef } from 'react'

export type State = Record<string | number | symbol, any>
export type StateListener<T> = (state: T) => void
export type StateSelector<T extends State, U> = (state: T) => U
export type PartialState<T extends State> =
  | Partial<T>
  | ((state: T) => Partial<T>)
export type EqualityChecker<T> = (state: T, newState: any) => boolean
export interface SubscribeOptions<T extends State, U> {
  selector?: StateSelector<T, U>
  equalityFn?: EqualityChecker<U>
  currentSlice?: U
  subscribeError?: Error
}
export type StateCreator<T extends State> = (
  set: SetState<T>,
  get: GetState<T>,
  api: StoreApi<T>
) => T
export type SetState<T extends State> = (partial: PartialState<T>) => void
export type GetState<T extends State> = () => T
export type ReturnState<T extends State, U> = U extends T ? T : U
export type Subscribe<T extends State> = <U>(
  listener: StateListener<U | void>,
  options?: SubscribeOptions<T, U>
) => () => void
export type Destroy = () => void
export type UseStore<T extends State> = <U>(
  selector?: StateSelector<T, U>,
  equalityFn?: EqualityChecker<U>
) => ReturnState<T, U>
export interface StoreApi<T extends State> {
  setState: SetState<T>
  getState: GetState<T>
  subscribe: Subscribe<T>
  destroy: Destroy
}

const forceUpdateReducer = (state: number) => state + 1
// For server-side rendering: https://github.com/react-spring/zustand/pull/34
const useIsoLayoutEffect =
  typeof window === 'undefined' ? useEffect : useLayoutEffect

export default function create<TState extends State>(
  createState: StateCreator<TState>
): [UseStore<TState>, StoreApi<TState>] {
  let state: TState

Review comment (suggestion):
No need for `ReturnState` because the return value for `useStore()` and `useStore(selector)` would be declared in the interface.

Code after:
import { useEffect, useLayoutEffect, useReducer, useRef } from 'react'

export type State = Record<string | number | symbol, any>
export type StateListener<T> = (state: T) => void
export type StateSelector<T extends State, U> = (state: T) => U
export type PartialState<T extends State> =
  | Partial<T>
  | ((state: T) => Partial<T>)
export type EqualityChecker<T> = (state: T, newState: any) => boolean
export interface SubscribeOptions<T extends State, U> {
  selector?: StateSelector<T, U>
  equalityFn?: EqualityChecker<U>
  currentSlice?: U
  subscribeError?: Error
}
export type StateCreator<T extends State> = (
  set: SetState<T>,
  get: GetState<T>,
  api: StoreApi<T>
) => T
export type SetState<T extends State> = (partial: PartialState<T>) => void
export type GetState<T extends State> = () => T
export type Subscribe<T extends State> = <U>(
  listener: StateListener<U | void>,
  options?: SubscribeOptions<T, U>
) => () => void
export type Destroy = () => void
export interface UseStore<T extends State> {
  (): T
  <U>(selector: StateSelector<T, U>, equalityFn?: EqualityChecker<U>): U
}
export interface StoreApi<T extends State> {
  setState: SetState<T>
  getState: GetState<T>
  subscribe: Subscribe<T>
  destroy: Destroy
}

const forceUpdateReducer = (state: number) => state + 1
// For server-side rendering: https://github.com/react-spring/zustand/pull/34
const useIsoLayoutEffect =
  typeof window === 'undefined' ? useEffect : useLayoutEffect

export default function create<TState extends State>(
  createState: StateCreator<TState>
): [UseStore<TState>, StoreApi<TState>] {
  let state: TState
  const listeners: Set<StateListener<void>> = new Set()