Skip to content

Commit

Permalink
fix: types for optional stores (#94)
Browse files Browse the repository at this point in the history
* fix: types for optional stores

* fix: `getStoreType` recursion

* test: stores with optional properties
  • Loading branch information
filoozom authored Sep 1, 2022
1 parent 11fa158 commit cdc6ea6
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 5 deletions.
10 changes: 5 additions & 5 deletions package/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,22 @@ export type HocFunc<S, R extends ComponentClass<any> = ComponentClass<any>> = (
export type Listener<S extends Store> = (params: Params<S>) => void;

export type getStoreType<S extends Store> = {
[key in keyof S]: S[key] extends Store
? useStoreType<S[key]> & HookDry<S[key]> : HookDry<S[key]>;
[key in keyof S]-?: NonNullable<S[key]> extends Store
? getStoreType<S[key]> & HookDry<S[key]> : HookDry<S[key]>;
};

export type setStoreType<S extends Store> = {
[key in keyof S]: S[key] extends Store
[key in keyof S]-?: NonNullable<S[key]> extends Store
? setStoreType<S[key]> & Setter<S[key]> : Setter<S[key]>;
};

export type useStoreType<S extends Store> = {
[key in keyof S]: S[key] extends Store
[key in keyof S]-?: NonNullable<S[key]> extends Store
? useStoreType<S[key]> & Hook<S[key]> : Hook<S[key]>;
};

export type withStoreType<S extends Store> = {
[key in keyof S]: S[key] extends Store
[key in keyof S]-?: NonNullable<S[key]> extends Store
? withStoreType<S[key]> & HocFunc<S[key]>
: HocFunc<S[key]>;
};
Expand Down
37 changes: 37 additions & 0 deletions tests/useStore.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<Store>();

function Test() {
const [user] = useStore.user();
const [username] = useStore.user.username();
return (
<>
<div data-testid="username">{username}</div>
<div data-testid="user">{JSON.stringify(user)}</div>
</>
);
}

render(<Test />);

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"}');
});
});

0 comments on commit cdc6ea6

Please sign in to comment.