From b169bbc74b45e4371674a562aa4df33f6fff7c13 Mon Sep 17 00:00:00 2001 From: Andrew Jarrett Date: Wed, 24 Apr 2024 05:26:52 -0500 Subject: [PATCH 1/5] fix: `typeof partial` inference; simplify `SetStateInternal` --- src/vanilla.ts | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/vanilla.ts b/src/vanilla.ts index df817932fe..2f39496161 100644 --- a/src/vanilla.ts +++ b/src/vanilla.ts @@ -1,9 +1,8 @@ -type SetStateInternal = { - _( - partial: T | Partial | { _(state: T): T | Partial }['_'], - replace?: boolean | undefined, - ): void -}['_'] +type NextState = never | Partial | ((state: T) => Partial) +type SetStateInternal = ( + partial: NextState, + replace?: boolean | undefined, +) => void export interface StoreApi { setState: SetStateInternal @@ -65,12 +64,7 @@ const createStoreImpl: CreateStoreImpl = (createState) => { const listeners: Set = new Set() const setState: StoreApi['setState'] = (partial, replace) => { - // TODO: Remove type assertion once https://github.com/microsoft/TypeScript/issues/37663 is resolved - // https://github.com/microsoft/TypeScript/issues/37663#issuecomment-759728342 - const nextState = - typeof partial === 'function' - ? (partial as (state: TState) => TState)(state) - : partial + const nextState = typeof partial === 'function' ? partial(state) : partial if (!Object.is(nextState, state)) { const previousState = state state = From a02ca2c4330876caad48fc9dcc18ab866675e09c Mon Sep 17 00:00:00 2001 From: Andrew Jarrett Date: Wed, 24 Apr 2024 05:29:59 -0500 Subject: [PATCH 2/5] docs: refinement --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2452aa4021..1575ffe7d9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,7 +34,7 @@ If you want to contribute to the [documentation](./docs/): As a temporary measure, you can do the following (don't commit any changes made in the pmndrs/website repo): - In your own Zustand fork, create a new working branch - (further related to as `[your-branch]`); + (referred to as `[your-branch]` going forward); - Inside website codebase, open `src/data/libraries.ts`; - Within the `zustand` key, change `docs: 'pmndrs/zustand/main/docs'` From fbc204df2489e2017db9c819306c237eff625612 Mon Sep 17 00:00:00 2001 From: Andrew Jarrett Date: Wed, 24 Apr 2024 09:23:01 -0500 Subject: [PATCH 3/5] chore: further simplification --- src/vanilla.ts | 49 +++++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/src/vanilla.ts b/src/vanilla.ts index 2f39496161..da553aa6fc 100644 --- a/src/vanilla.ts +++ b/src/vanilla.ts @@ -1,18 +1,17 @@ -type NextState = never | Partial | ((state: T) => Partial) -type SetStateInternal = ( - partial: NextState, - replace?: boolean | undefined, -) => void - -export interface StoreApi { - setState: SetStateInternal - getState: () => T - getInitialState: () => T - subscribe: (listener: (state: T, prevState: T) => void) => () => void - /** - * @deprecated Use `unsubscribe` returned by `subscribe` - */ - destroy: () => void +// This type intentionally shadows globalThis.Partial. +// Keeping the name the same hides an implementation +// detail from users, which is that this version is +// evaluates its type argument _greedily_. +type Partial = never | { [K in keyof T]+?: T[K] } + +export interface StoreApi extends Deprecated.Api { + getState(): T + setState( + partial: Partial | ((state: T) => Partial), + replace?: boolean, + ): void + subscribe(listener: (state: T, prevState: T) => void): () => void + getInitialState(): T } type Get = K extends keyof T ? T[K] : F @@ -20,10 +19,10 @@ type Get = K extends keyof T ? T[K] : F export type Mutate = number extends Ms['length' & keyof Ms] ? S : Ms extends [] - ? S - : Ms extends [[infer Mi, infer Ma], ...infer Mrs] - ? Mutate[Mi & StoreMutatorIdentifier], Mrs> - : never + ? S + : Ms extends [[infer Mi, infer Ma], ...infer Mrs] + ? Mutate[Mi & StoreMutatorIdentifier], Mrs> + : never export type StateCreator< T, @@ -37,7 +36,7 @@ export type StateCreator< ) => U) & { $$storeMutators?: Mos } // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-interface -export interface StoreMutators {} +export interface StoreMutators { } export type StoreMutatorIdentifier = keyof StoreMutators type CreateStore = { @@ -177,3 +176,13 @@ export type GetState = () => T * @deprecated Use `StoreApi['destroy']` instead of `Destroy`. */ export type Destroy = () => void + +/* eslint-disable-next-line @typescript-eslint/no-namespace */ +declare namespace Deprecated { + interface Api { + /** + * @deprecated Use `unsubscribe` returned by `subscribe` + */ + destroy(): void + } +} From d0296cbb1b4b6ac4d50077a0ba34a30102687be3 Mon Sep 17 00:00:00 2001 From: Andrew Jarrett Date: Wed, 24 Apr 2024 09:24:20 -0500 Subject: [PATCH 4/5] chore: formatting --- src/vanilla.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vanilla.ts b/src/vanilla.ts index da553aa6fc..910fa0a1d4 100644 --- a/src/vanilla.ts +++ b/src/vanilla.ts @@ -19,10 +19,10 @@ type Get = K extends keyof T ? T[K] : F export type Mutate = number extends Ms['length' & keyof Ms] ? S : Ms extends [] - ? S - : Ms extends [[infer Mi, infer Ma], ...infer Mrs] - ? Mutate[Mi & StoreMutatorIdentifier], Mrs> - : never + ? S + : Ms extends [[infer Mi, infer Ma], ...infer Mrs] + ? Mutate[Mi & StoreMutatorIdentifier], Mrs> + : never export type StateCreator< T, @@ -36,7 +36,7 @@ export type StateCreator< ) => U) & { $$storeMutators?: Mos } // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-interface -export interface StoreMutators { } +export interface StoreMutators {} export type StoreMutatorIdentifier = keyof StoreMutators type CreateStore = { From cd038f0acbf01167927dca97786bcc2b6c9307b0 Mon Sep 17 00:00:00 2001 From: Andrew Jarrett Date: Wed, 24 Apr 2024 09:26:18 -0500 Subject: [PATCH 5/5] chore: simplifies comment --- src/vanilla.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/vanilla.ts b/src/vanilla.ts index 910fa0a1d4..2a0c79af16 100644 --- a/src/vanilla.ts +++ b/src/vanilla.ts @@ -1,7 +1,4 @@ -// This type intentionally shadows globalThis.Partial. -// Keeping the name the same hides an implementation -// detail from users, which is that this version is -// evaluates its type argument _greedily_. +// Shows users better types sooner than globalThis.Partial type Partial = never | { [K in keyof T]+?: T[K] } export interface StoreApi extends Deprecated.Api {