使用 Vue3 和 TypeScript 将 Pinia Store 作为 Prop 传递
P粉899950720
P粉899950720 2023-08-25 18:40:12
[Vue.js讨论组]
<p>我正在使用 Typescript、Pinia 和 Vue3,并且有一个 <code>MenuButton</code> 组件,我希望能够传递用于菜单打开状态以及要显示的操作的 Pinia 存储/隐藏。应用程序中有几个不同的菜单,因此我希望能够将它们传入,并且它们都使用相同的工厂来定义商店。我正在尝试弄清楚如何让所有这些都与打字稿一起使用。</p> <pre class="lang-js prettyprint-override"><code>// nav.store.ts import { defineStore } from &quot;pinia&quot;; import { useStorage } from &quot;@vueuse/core&quot;; import type { RemovableRef } from &quot;@vueuse/core&quot;; export interface MenuStore { isOpen: RemovableRef&lt;boolean&gt;, toggle(force?: boolean) : void, open(): void, close(): void, } interface State { isOpen: RemovableRef&lt;boolean&gt;; } function menuStoreFactory(id: string) { return defineStore(id, { state: () : State =&gt; ({ isOpen: useStorage(`${id}-open`, false), }), actions: { toggle(force?: boolean) { this.isOpen = force != undefined ? force : !this.isOpen; }, open() { this.isOpen = true; }, close() { this.isOpen = false; } } }); } export const useMainMenuStore = menuStoreFactory('mainMenu'); export const useMobileMenuStore = menuStoreFactory('mobileMenu'); </code></pre> <pre class="lang-js prettyprint-override"><code>// setup script for the menu button component import { MenuIcon, MenuLeftIcon } from &quot;@/icons&quot;; import type { MenuStore } from &quot;@/modules/nav/nav.store&quot;; interface Props { controller: MenuStore } const props = defineProps&lt;Props&gt;(); </code></pre> <p>那么用法就非常简单了:</p> <pre class="lang-html prettyprint-override"><code>&lt;template&gt; &lt;MenuButton :controller=&quot;mainMenu&quot; &gt;&lt;/MenuButton&gt; &lt;/template&gt; &lt;script setup lang=ts&quot;&gt; const mainMenu = useMainMenuStore(); &lt;/script&gt; </code></pre> <p>在当前界面中,我收到了道具不匹配的错误。经过一番研究,我将界面变成了以下内容,修复了使用错误,但随后在 <code>MenuButton</code> 组件中引发了 <code>toggle()</code> 和 <code>isOpen< 的错误/code> 尚未解决。</p> <pre class="lang-js prettyprint-override"><code>export interface MenuStore extends PiniaCustomStateProperties&lt;{ isOpen: RemovableRef&lt;boolean&gt;, toggle(force?: boolean) : void, open(): void, close(): void, }&gt; {} </code></pre> <p>另一个接近的尝试调整是:</p> <pre class="lang-js prettyprint-override"><code>export interface MenuStore extends Store&lt;string, { isOpen: RemovableRef&lt;boolean&gt;, toggle(force?: boolean) : void, open(): void, close(): void, }&gt; {} </code></pre> <p>这导致了使用时出现此错误,但组件中没有错误</p> <pre class="brush:php;toolbar:false;">Type _StoreWithState&lt;string, State, {}, {toggle(force?: boolean): void, close(): void, open(): void}&gt; &amp; UnwrapRef&lt;State&gt; &amp; _StoreWithGetters&lt;{}&gt; &amp; {toggle(force?: boolean): void, close(): void, open(): void} &amp; PiniaCustomProperties&lt;string, State, {}, {toggle(force?: boolean): void, close(): void, open(): void}&gt; &amp; PiniaCustomStateProperties&lt;State&gt; is not assignable to type MenuStore ...   Type PiniaCustomStateProperties&lt;State&gt; is not assignable to type MenuStore</pre></p>
P粉899950720
P粉899950720

全部回复(1)
P粉187677012

您的问题似乎主要是关于您需要的类型/接口,所以我会回答这个问题。

您可以简单地使用返回的存储的类型,而不是自己编写类型。

您有一个工厂函数,它返回 defineStore 的返回值,它本身就是一个返回存储的函数。因此,可以使用 typeof 获取工厂函数的类型,然后使用 TypeScript 的 ReturnType 帮助器深入了解返回类型,从而找到存储的类型。

以下应该是您所需要的:

export type MenuStore = ReturnType<ReturnType<typeof menuStoreFactory>>

细分:

ReturnType<                 // C
  ReturnType<               // B
    typeof menuStoreFactory // A
  >
>
  • A:获取工厂函数的类型。
  • B:获取工厂函数的返回类型,即defineStore的返回值。这本身就是一个返回存储的函数。
  • C: 获取该函数的返回类型。这是商店本身的类型。
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号