Skip to content

Commit

Permalink
test: add example middleware that modifies getState w/o setState
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisvander committed Aug 24, 2024
1 parent 1e86925 commit 3c5ac54
Showing 1 changed file with 49 additions and 2 deletions.
51 changes: 49 additions & 2 deletions tests/middlewareTypes.test.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* eslint @typescript-eslint/no-unused-expressions: off */ // FIXME
/* eslint react-compiler/react-compiler: off */

import { describe, expect, it } from 'vitest'
import { describe, expect, expectTypeOf, it } from 'vitest'
import { create } from 'zustand'
import type { StoreApi } from 'zustand'
import type { StateCreator, StoreApi, StoreMutatorIdentifier } from 'zustand'
import {
combine,
devtools,
Expand All @@ -19,6 +19,27 @@ type CounterState = {
inc: () => void
}

type ExampleStateCreator<T, A> = <
Mps extends [StoreMutatorIdentifier, unknown][] = [],
Mcs extends [StoreMutatorIdentifier, unknown][] = [],
U = T,
>(
f: StateCreator<T, [...Mps, ['org/example', A]], Mcs>,
) => StateCreator<T, Mps, [['org/example', A], ...Mcs], U & A>

type Write<T, U> = Omit<T, keyof U> & U
type StoreModifyAllButSetState<S, A> = S extends {
getState: () => infer T
}
? Omit<StoreApi<T & A>, 'setState'>
: never

declare module 'zustand/vanilla' {
interface StoreMutators<S, A> {
'org/example': Write<S, StoreModifyAllButSetState<S, A>>
}
}

describe('counter state spec (no middleware)', () => {
it('no middleware', () => {
const useBoundStore = create<CounterState>((set, get) => ({
Expand Down Expand Up @@ -64,6 +85,32 @@ describe('counter state spec (single middleware)', () => {
immer(() => ({ count: 0 })),
)
expect(testSubtyping).toBeDefined()

const exampleMiddleware = ((initializer) =>
initializer) as ExampleStateCreator<CounterState, { additional: number }>

const testDerivedSetStateType = create<CounterState>()(
exampleMiddleware(
immer((set, get) => ({
count: 0,
inc: () =>
set((state) => {
state.count = get().count + 1
}),
})),
),
)
expect(testDerivedSetStateType).toBeDefined()
// the type of the `getState` should include our new property
expectTypeOf(testDerivedSetStateType.getState()).toMatchTypeOf<{
additional: number
}>()
// the type of the `setState` should not include our new property
expectTypeOf<
Parameters<typeof testDerivedSetStateType.setState>[0]
>().not.toMatchTypeOf<{
additional: number
}>()
})

it('redux', () => {
Expand Down

0 comments on commit 3c5ac54

Please sign in to comment.