使用Vue3和TypeScript传递Pinia商店作为 prop

yizd12fk  于 2023-01-21  发布在  TypeScript
关注(0)|答案(1)|浏览(223)

我正在使用Typescript,Pinia和Vue3,并有一个MenuButton组件,我希望能够传递一个Pinia商店,用于菜单打开状态以及显示/隐藏的操作。应用程序中有几个不同的菜单,因此我希望能够传递它们,它们都使用相同的工厂来定义存储。我正在尝试找出如何让所有这些都与typescript一起工作。

// nav.store.ts

import { defineStore } from "pinia";
import { useStorage } from "@vueuse/core";
import type { RemovableRef } from "@vueuse/core";

export interface MenuStore {
    isOpen: RemovableRef<boolean>,
    toggle(force?: boolean) : void,
    open(): void,
    close(): void,
}

interface State {
    isOpen: RemovableRef<boolean>;
}

function menuStoreFactory(id: string) {
    return defineStore(id, {
        state: () : State => ({
            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');
// setup script for the menu button component

import { MenuIcon, MenuLeftIcon } from "@/icons";
import type { MenuStore } from "@/modules/nav/nav.store";

interface Props {
    controller: MenuStore
}

const props = defineProps<Props>();

那么用法就非常简单了:

<template>
    <MenuButton
        :controller="mainMenu"
    ></MenuButton>
</template>
<script setup lang=ts">
    const mainMenu = useMainMenuStore();
</script>

使用当前接口时,我遇到了一个属性不匹配的错误。经过一番研究,我将接口转换为以下形式,修复了使用错误,但随后在MenuButton组件中抛出了一个错误,即toggle()isOpen无法解析。

export interface MenuStore extends PiniaCustomStateProperties<{
    isOpen: RemovableRef<boolean>,
    toggle(force?: boolean) : void,
    open(): void,
    close(): void,
}> {}

另一个接近成功的尝试是:

export interface MenuStore extends Store<string, {
    isOpen: RemovableRef<boolean>,
    toggle(force?: boolean) : void,
    open(): void,
    close(): void,
}> {}

导致使用错误,但组件中没有错误

Type _StoreWithState<string, State, {}, {toggle(force?: boolean): void, close(): void, open(): void}> & UnwrapRef<State> & _StoreWithGetters<{}> & {toggle(force?: boolean): void, close(): void, open(): void} & PiniaCustomProperties<string, State, {}, {toggle(force?: boolean): void, close(): void, open(): void}> & PiniaCustomStateProperties<State> is not assignable to type MenuStore ...   Type PiniaCustomStateProperties<State> is not assignable to type MenuStore
7cwmlq89

7cwmlq891#

你的问题似乎主要是关于你需要的类型/接口,所以我会回答。
您可以直接使用返回的存储的类型,而不必自己编写类型。
您有一个返回defineStore返回值的工厂函数,而defineStore本身就是一个返回存储的函数。因此,可以使用typeof获取工厂函数的类型,然后使用TypeScript的ReturnType帮助器深入查看返回类型,从而找到存储的类型。
以下内容应该是您所需要的全部内容:

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

分解:

ReturnType<                 // C
  ReturnType<               // B
    typeof menuStoreFactory // A
  >
>
      • A:**获取工厂函数的类型。
      • B:**获取工厂函数的返回类型,它是defineStore的返回。它本身是一个返回存储的函数。
      • C:**获取上述函数的返回类型,这是存储本身的类型。

相关问题