# Type a store with TypeScript

Use a state type to check a store's fields and actions, then derive the complete store type for components and utilities.

## When to use this

Use this pattern when you want TypeScript to check the store's initial state and action signatures, and want one reusable type that stays aligned with the store. Install [`zustand`](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/zustand) if it is not already in your project:

```bash
npm install zustand
```

## 1. Declare the state shape and create the store

Pass your state-and-actions type to [`create`](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/zustand#create) in its curried form, `create<State>()(creator)`. The type argument checks the object returned by the creator, while TypeScript infers the `set` callback from that type. The extra call lets you provide the state type while leaving the creator's other types inferred.

Use [`ExtractState`](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/zustand#extractstate) to derive and export the complete state-and-actions type from the bound store.

```ts title="store.ts"
import { create, type ExtractState } from 'zustand'

interface BearState {
  bears: number
  food: string
  feed: (food: string) => void
}

export const useBearStore = create<BearState>()((set) => ({
  bears: 2,
  food: 'honey',
  feed: (food) => set({ food }),
}))

export type BearStoreState = ExtractState<typeof useBearStore>
```

The store starts with two bears and honey. TypeScript checks that the returned object supplies both state fields and the `feed` action, and checks the action's argument as a string.

## 2. Reuse the store type

The exported alias gives utilities the full state-and-actions type without a second version of the store's shape.

```ts title="summary.ts"
import type { BearStoreState } from './store'

export function describeBears(state: BearStoreState): string {
  return `${state.bears} bears eat ${state.food}`
}
```

In a React component, read the store and pass it to the typed utility. The button calls the colocated action; the displayed summary changes from honey to berries.

```tsx title="App.tsx"
import { useBearStore } from './store'
import { describeBears } from './summary'

export function App() {
  const state = useBearStore()

  return (
    <main>
      <p>{describeBears(state)}</p>
      <button onClick={() => state.feed('berries')}>Feed berries</button>
    </main>
  )
}
```

For the React entry-point code that mounts `App`, use [React quick start](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/react-quick-start#2-mount-the-component); this page adds the typed store contract and reusable state-and-actions type.

## What to watch for

- Keep state updates immutable. If you update a nested object, copy its existing fields; see [Update nested state](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/update-nested-state).
- When a component needs only part of the state, select that part rather than subscribing to the whole store; see [Select state efficiently](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/select-state-efficiently).
- Do not call `get` synchronously while the initial state creator is running: the state has not been created yet. Use it from an action after store creation instead.

## See it running

Open the [Zustand live demo](https://zustand-demo.pmnd.rs/) to see a running Zustand application.

## Related

- [React quick start](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/react-quick-start)
- [How Zustand works](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/how-zustand-works)
- [Compose a store from slices](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/compose-a-store-from-slices)
