Skip to content

Commit

Permalink
fix: fix types when used with zustand immer middleware
Browse files Browse the repository at this point in the history
fix #953
  • Loading branch information
patdx committed Jan 26, 2024
1 parent 0711af2 commit 715457e
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 10 deletions.
14 changes: 13 additions & 1 deletion apps/zustand-rx-web/src/components/example/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,25 @@
import { toStream } from 'zustand-rx';
import { combine } from 'zustand/middleware';
import { createStore } from 'zustand/vanilla';
import { immer } from 'zustand/middleware/immer';

export const store = createStore(
combine({ bears: 0 }, (set) => ({
increment: () => set((state) => ({ bears: state.bears + 1 })),
}))
})),
);

export const immerStore = createStore(
immer(
combine({ bears: 0 }, (set) => ({
increment: () => set((state) => ({ bears: state.bears + 1 })),
})),
),
);

// Test to make sure immer store works too
toStream(immerStore, (store) => store.bears);

/* Observable<number> */
export const bears$ = toStream(store, (state) => state.bears, {
fireImmediately: true,
Expand Down
4 changes: 2 additions & 2 deletions libs/zustand-rx/src/lib/zustand-rx.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ describe('zustand-rx', () => {
const store = createStore(
combine({ bears: 0 }, (set) => ({
increase: (by: number) => set((state) => ({ bears: state.bears + by })),
}))
})),
);

let bears: any;
let bears: number | null = null;

const bears$ = toStream(store, (state) => state.bears, {
fireImmediately: true,
Expand Down
16 changes: 11 additions & 5 deletions libs/zustand-rx/src/lib/zustand-rx.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
/* eslint-disable @typescript-eslint/ban-types */
import { Observable } from 'rxjs';
import { distinctUntilChanged, map } from 'rxjs/operators';
import type { StoreApi } from 'zustand/vanilla';

export type StateValueOf<TStore> = TStore extends StoreApi<infer TState>
? TState
: never;
// Based on here: https://github.com/pmndrs/zustand/blob/50a8677dba4acecc1e313dcb08d4cf2ac1ab918c/src/vanilla.ts#L8
// Inlined the type to fix issue:
// https://github.com/patdx/zustand-rx/issues/953
type StoreApi<T> = {
getState: () => T;
subscribe: (listener: (state: T, prevState: T) => void) => () => void;
};

export type StateValueOf<TStore> =
TStore extends StoreApi<infer TState> ? TState : never;

/**
* Create a zustand selector as an RxJS observable, inspired
Expand All @@ -14,7 +20,7 @@ export type StateValueOf<TStore> = TStore extends StoreApi<infer TState>
export const toStream = <
// eslint-disable-next-line @typescript-eslint/no-explicit-any
TStore extends StoreApi<any>,
TState extends object = StateValueOf<TStore>,
TState = StateValueOf<TStore>,
TSlice = TState,
>(
store: TStore,
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
"eslint-plugin-react": "7.33.2",
"eslint-plugin-react-hooks": "4.6.0",
"husky": "9.0.6",
"immer": "10.0.3",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"jsdom": "24.0.0",
Expand Down
11 changes: 9 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 715457e

Please sign in to comment.