Skip to content

Commit d2ac820

Browse files
vorant94dai-shi
andauthored
feat(types): Make ExtractState public (#2935)
* make ExtractState public and move it to vanilla * add docs on the matter * Update vanilla.ts --------- Co-authored-by: Daishi Kato <dai-shi@users.noreply.github.com>
1 parent 929b547 commit d2ac820

3 files changed

Lines changed: 18 additions & 2 deletions

File tree

docs/guides/typescript.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,21 @@ It isn't really a lie because `{ bears: number }` is still a subtype of `{ bears
161161

162162
Note that we don't use the curried version when using `combine` because `combine` "creates" the state. When using a middleware that creates the state, it isn't necessary to use the curried version because the state now can be inferred. Another middleware that creates state is `redux`. So when using `combine`, `redux`, or any other custom middleware that creates the state, we don't recommend using the curried version.
163163

164+
If you want to infer state type also outside of state declaration, you can use the `ExtractState` type helper:
165+
166+
```ts
167+
import { create, ExtractState } from 'zustand'
168+
import { combine } from 'zustand/middleware'
169+
170+
type BearState = ExtractState<typeof useBearStore>
171+
172+
const useBearStore = create(
173+
combine({ bears: 0 }, (set) => ({
174+
increase: (by: number) => set((state) => ({ bears: state.bears + by })),
175+
})),
176+
)
177+
```
178+
164179
## Using middlewares
165180

166181
You do not have to do anything special to use middlewares in TypeScript.

src/react.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import React from 'react'
22
import { createStore } from './vanilla.ts'
33
import type {
4+
ExtractState,
45
Mutate,
56
StateCreator,
67
StoreApi,
78
StoreMutatorIdentifier,
89
} from './vanilla.ts'
910

10-
type ExtractState<S> = S extends { getState: () => infer T } ? T : never
11-
1211
type ReadonlyStoreApi<T> = Pick<
1312
StoreApi<T>,
1413
'getState' | 'getInitialState' | 'subscribe'

src/vanilla.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ export interface StoreApi<T> {
1313
subscribe: (listener: (state: T, prevState: T) => void) => () => void
1414
}
1515

16+
export type ExtractState<S> = S extends { getState: () => infer T } ? T : never
17+
1618
type Get<T, K, F> = K extends keyof T ? T[K] : F
1719

1820
export type Mutate<S, Ms> = number extends Ms['length' & keyof Ms]

0 commit comments

Comments
 (0)