First of all, please forgive me for being a translator.
I would like to type check by adding the type as jsdoc to the slice pattern example described in the zustand official document.
The type for create is not exported, so it cannot be used.
How can I check the type in useBoundStore in component when using slice pattern?
// @ts-check
import { create } from 'zustand';
/**
* @typedef {{
* bears: number,
* addBear: () => void,
* eatFish: () => void,
* }} BearSlice
*
* @typedef {{
* fishes: number,
* addFish: () => void,
* }} FishSlice
*/
/**
* @typedef {import('zustand').StateCreator<BearSlice & FishSlice, [], [], FishSlice>} FishSliceCreator
*
* @type {FishSliceCreator}
*/
export const createFishSlice = (set) => ({
fishes: 0,
addFish: () => set((state) => ({ fishes: state.fishes + 1 })),
});
/**
* @typedef {import('zustand').StateCreator<BearSlice & FishSlice, [], [], BearSlice>} BearSliceCreator
*
* @type {BearSliceCreator}
*/
export const createBearSlice = (set) => ({
bears: 0,
addBear: () => set((state) => ({ bears: state.bears + 1 })),
eatFish: () => set((state) => ({ fishes: state.fishes - 1 })),
});
/**
* ???
*/
export const useBoundStore = create((...a) => ({
...createBearSlice(...a),
...createFishSlice(...a),
}));
I want autocomplete for zustand's create function in component. However, in zustand, the create type is not exported, so it cannot be used.
If you use StateCreator, it seems to come out, but if you use middleware devtools or immer, it doesn't seem to work well.
If I add @ts-check and add middleware(devtools, immer) I get an ts error. Below is a screenshot of the error part and the typedef for the slice type.
Anything I'm missing?
slice typedef
/**
* @typedef {import('zustand').StateCreator<
* BearSlice & FishSlice,
* [],
* [["zustand/devtools", never], ["zustand/immer", never]],
* FishSlice
* >} FishSliceCreator
*/
/**
* @typedef {import('zustand').StateCreator<
* BearSlice & FishSlice,
* [],
* [["zustand/devtools", never], ["zustand/immer", never]],
* BearSlice
* >} BearSliceCreator
*/
/**
* @param {import('zustand').StateCreator<BearSlice & FishSlice>} f
*/
const middleware = (f) => devtools(immer(f));
Hovering over useBoundStore
gives me this:
and luckily zustand does export these two types, so we can use them in the JSDoc:
/**
* @type {import("zustand").UseBoundStore<import("zustand").StoreApi<unknown>>}
*/
export const useBoundStore = create((...a) => ({
...createBearSlice(...a),
...createFishSlice(...a),
}));