Zustand结合TypeScript使用persist中间件出现类型错误,求助
我想用Zustand的persist中间件实现页面刷新后保留状态值,但编写以下代码时TypeScript抛出错误:
import { create } from "zustand"; import { persist } from "zustand/middleware"; type CoverImage = { isOpen: boolean; onOpen: () => void; onClose: () => void; }; export const useCoverImage = create( persist<CoverImage>( (set) => ({ isOpen: false, onClose() { set({ isOpen: false }); }, onOpen() { set({ isOpen: true }); }, }), { name: "coverImage" } ) );
错误信息:
没有匹配的重载调用。
重载1共3个,'(initializer: StateCreator<CoverImage, [], [never, unknown][]>): UseBoundStore',给出如下错误。
类型为'StateCreator<CoverImage, [], [["zustand/persist", CoverImage]]>'的参数无法赋值给类型为'StateCreator<CoverImage, [], [never, unknown][]>'的参数。
类型'StateCreator<CoverImage, [], [["zustand/persist", CoverImage]]>'无法赋值给类型'{ $$storeMutators?: [never, unknown][] | undefined; }'。
属性'$$storeMutators'的类型不兼容。
类型'[["zustand/persist", CoverImage]] | undefined'无法赋值给类型'[never, unknown][] | undefined'。
错误原因
这个类型不匹配问题,是因为persist中间件会给StateCreator添加额外的$$storeMutators元数据类型,而create函数默认的泛型参数未包含该中间件的类型信息,导致TypeScript无法正确推断类型兼容性。
解决方法
方法一:使用curried形式的create(推荐)
通过先指定状态类型再传入persist中间件的方式,让TS自动处理中间件的类型推断:
import { create } from "zustand"; import { persist } from "zustand/middleware"; type CoverImage = { isOpen: boolean; onOpen: () => void; onClose: () => void; }; export const useCoverImage = create<CoverImage>()( persist( (set) => ({ isOpen: false, onClose() { set({ isOpen: false }); }, onOpen() { set({ isOpen: true }); }, }), { name: "coverImage" } ) );
方法二:显式指定包含中间件的StateCreator类型
如果需要更精确的类型控制,可以手动定义包含persist中间件的StateCreator类型:
import { create, StateCreator } from "zustand"; import { persist, PersistOptions } from "zustand/middleware"; type CoverImage = { isOpen: boolean; onOpen: () => void; onClose: () => void; }; // 定义包含persist中间件的StateCreator类型 type PersistedStateCreator = StateCreator< CoverImage, [], [["zustand/persist", CoverImage]] >; export const useCoverImage = create( persist<CoverImage, PersistOptions<CoverImage>>( (set) => ({ isOpen: false, onClose() { set({ isOpen: false }); }, onOpen() { set({ isOpen: true }); }, }), { name: "coverImage" } ) as PersistedStateCreator );
内容的提问来源于stack exchange,提问作者Captai-N

