Skip to content

Commit

Permalink
feat: support slices pattern type (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
yjrhgvbn authored Jan 24, 2024
1 parent f963963 commit 043d1b6
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
47 changes: 46 additions & 1 deletion src/computed.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { create } from "zustand"
import { create, StateCreator } from "zustand"
import { computed, ComputedStateOpts } from "./computed"

type Store = {
Expand Down Expand Up @@ -132,3 +132,48 @@ describe("custom config", () => {
expect(computeStateMock).toHaveBeenCalledTimes(4)
})
})

describe("slices pattern", () => {
const computeStateMock = jest.fn(computeState)
const makeStore = () => {
const createXySlice = computed<Store, ComputedStore, [], [], Pick<Store, "count" | "dec">>(
(set) => ({
count: 1,
dec: () => set((state) => ({ count: state.count - 1 })),
}),
computeStateMock
)
const createCountSlice: StateCreator<Store & ComputedStore, [], [], Pick<Store, "x" | "y" | "inc">> = (set) => ({
x: 1,
y: 1,
// this should not trigger compute function
inc: () => set((state) => ({ count: state.count + 2 })),
})
return create<Store & ComputedStore>()((...a) => ({
...createXySlice(...a),
...createCountSlice(...a),
}))
}

beforeEach(() => {
computeStateMock.mockClear()
})

test("computed works on slices pattern example", () => {
const useStore = makeStore()
expect(computeStateMock).toHaveBeenCalledTimes(1)
expect(useStore.getState().count).toEqual(1)
expect(useStore.getState().countSq).toEqual(1)
useStore.getState().inc()
expect(useStore.getState().count).toEqual(3)
expect(useStore.getState().countSq).toEqual(1)
expect(computeStateMock).toHaveBeenCalledTimes(1)
useStore.getState().dec()
expect(useStore.getState().count).toEqual(2)
expect(useStore.getState().countSq).toEqual(4)
expect(computeStateMock).toHaveBeenCalledTimes(2)
useStore.setState({ count: 4 })
expect(useStore.getState().countSq).toEqual(16)
expect(computeStateMock).toHaveBeenCalledTimes(3)
})
})
5 changes: 3 additions & 2 deletions src/computed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ export type ComputedStateCreator = <
A extends object,
Mps extends [StoreMutatorIdentifier, unknown][] = [],
Mcs extends [StoreMutatorIdentifier, unknown][] = [],
U = T,
>(
f: StateCreator<T, [...Mps, ["chrisvander/zustand-computed", A]], Mcs>,
f: StateCreator<T, [...Mps, ["chrisvander/zustand-computed", A]], Mcs, U>,
compute: (state: T) => A,
opts?: ComputedStateOpts<T>,
) => StateCreator<T, Mps, [["chrisvander/zustand-computed", A], ...Mcs], T & A>
) => StateCreator<T, Mps, [["chrisvander/zustand-computed", A], ...Mcs], U & A>

type Cast<T, U> = T extends U ? T : U
type Write<T, U> = Omit<T, keyof U> & U
Expand Down

0 comments on commit 043d1b6

Please sign in to comment.