Repository: pmndrs/zustand
File: tests/basic.test.tsx (TypeScript)

Code before:

  // Call all subscribers
  act(() => setState({ count: 1 }))

  expect((await findAllByText('count1: 1')).length).toBe(2)
  expect((await findAllByText('count2: 1')).length).toBe(1)
})

it('can use exposed types', () => {
  interface ExampleState extends State {
    num: number
    numGet: () => number
    numGetState: () => number
    numSet: (v: number) => void
    numSetState: (v: number) => void
  }

  const listener: StateListener<ExampleState> = (state) => {
    if (state) {
      const value = state.num * state.numGet() * state.numGetState()
      state.numSet(value)
      state.numSetState(value)
    }
  }
  const selector: StateSelector<ExampleState, number> = (state) => state.num
  const partial: PartialState<ExampleState, 'num' | 'numGet'> = {
    num: 2,
    numGet: () => 2,
  }
  const partialFn: PartialState<ExampleState, 'num' | 'numGet'> = (state) => ({
    ...state,
    num: 2,
  })
  const equalityFn: EqualityChecker<ExampleState> = (state, newState) =>
    state !== newState

  const storeApi = create<ExampleState>((set, get) => ({
    num: 1,
    numGet: () => get().num,
    numGetState: () => {
      // TypeScript can't get the type of storeApi when it trys to enforce the signature of numGetState.
      // Need to explicitly state the type of storeApi.getState().num or storeApi type will be type 'any'.
      const result: number = storeApi.getState().num
      return result
    },
    numSet: (v) => {
      set({ num: v })
    },
    numSetState: (v) => {
      storeApi.setState({ num: v })
    },

Review comment (suggestion):
I see. Looks more precise.
BTW, we should remove `extends State` in L664.

Code after:

  // Call all subscribers
  act(() => setState({ count: 1 }))

  expect((await findAllByText('count1: 1')).length).toBe(2)
  expect((await findAllByText('count2: 1')).length).toBe(1)
})

it('can use exposed types', () => {
  interface ExampleState {
    num: number
    numGet: () => number
    numGetState: () => number
    numSet: (v: number) => void
    numSetState: (v: number) => void
  }

  const listener: StateListener<ExampleState> = (state) => {
    if (state) {
      const value = state.num * state.numGet() * state.numGetState()
      state.numSet(value)
      state.numSetState(value)
    }
  }
  const selector: StateSelector<ExampleState, number> = (state) => state.num
  const partial: PartialState<ExampleState, 'num' | 'numGet'> = {
    num: 2,
    numGet: () => 2,
  }
  const partialFn: PartialState<ExampleState, 'num' | 'numGet'> = (state) => ({
    ...state,
    num: 2,
  })
  const equalityFn: EqualityChecker<ExampleState> = (state, newState) =>
    state !== newState

  const storeApi = create<ExampleState>((set, get) => ({
    num: 1,
    numGet: () => get().num,
    numGetState: () => {
      // TypeScript can't get the type of storeApi when it trys to enforce the signature of numGetState.
      // Need to explicitly state the type of storeApi.getState().num or storeApi type will be type 'any'.
      const result: number = storeApi.getState().num
      return result
    },
    numSet: (v) => {
      set({ num: v })
    },
    numSetState: (v) => {
      storeApi.setState({ num: v })
    },