From cdc6ea6fc810f7bca14f1e35794eb5f08b62d8ca Mon Sep 17 00:00:00 2001 From: Philippe Schommers Date: Thu, 1 Sep 2022 10:50:58 +0200 Subject: [PATCH] fix: types for optional stores (#94) * fix: types for optional stores * fix: `getStoreType` recursion * test: stores with optional properties --- package/types.ts | 10 +++++----- tests/useStore.test.tsx | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/package/types.ts b/package/types.ts index 925e683..5c431f7 100644 --- a/package/types.ts +++ b/package/types.ts @@ -70,22 +70,22 @@ export type HocFunc = ComponentClass> = ( export type Listener = (params: Params) => void; export type getStoreType = { - [key in keyof S]: S[key] extends Store - ? useStoreType & HookDry : HookDry; + [key in keyof S]-?: NonNullable extends Store + ? getStoreType & HookDry : HookDry; }; export type setStoreType = { - [key in keyof S]: S[key] extends Store + [key in keyof S]-?: NonNullable extends Store ? setStoreType & Setter : Setter; }; export type useStoreType = { - [key in keyof S]: S[key] extends Store + [key in keyof S]-?: NonNullable extends Store ? useStoreType & Hook : Hook; }; export type withStoreType = { - [key in keyof S]: S[key] extends Store + [key in keyof S]-?: NonNullable extends Store ? withStoreType & HocFunc : HocFunc; }; diff --git a/tests/useStore.test.tsx b/tests/useStore.test.tsx index 6c5817d..7dae707 100644 --- a/tests/useStore.test.tsx +++ b/tests/useStore.test.tsx @@ -203,4 +203,41 @@ describe('useStore', () => { .toMatchObject({cart: {items: [{name: 'new Item', price: 2}, undefined, {name: 'new Item', price: 1}]}}); expect(screen.getByTestId('item').textContent).toBe('Item: {"name":"new Item","price":1}'); }); + + it("should work with optional properties", () => { + type User = { + username: string; + }; + + type Store = { + user?: User; + }; + + const { useStore, getStore } = createStore(); + + function Test() { + const [user] = useStore.user(); + const [username] = useStore.user.username(); + return ( + <> +
{username}
+
{JSON.stringify(user)}
+ + ); + } + + render(); + + const update = getStore.user.username()[1]; + + expect(screen.getByTestId("username").textContent).toBe(""); + + act(() => update('myUsername')); + expect(screen.getByTestId("username").textContent).toBe("myUsername"); + expect(screen.getByTestId("user").textContent).toBe('{"username":"myUsername"}'); + + act(() => update((v) => v + "Update")); + expect(screen.getByTestId("username").textContent).toBe("myUsernameUpdate"); + expect(screen.getByTestId("user").textContent).toBe('{"username":"myUsernameUpdate"}'); + }); });