Тип хранилища Vuex с Typescript

Я пытаюсь сделать магазин Vuex дружественным к Typescript. Я строю магазин, как объяснил здесь. Однако, когда я обращаюсь к this.$store из компонента, это тип Store<any>.

Я не мог понять, как изменить его так, чтобы он по умолчанию был Store<MyState>, не требуя каждый раз приведения.

Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
14
0
4 740
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Вы можете объявить свойство в своем компоненте, чтобы машинописный текст применил типизацию. Я постоянно использую это для $refs, но он работает и для $store. Вам не нужно ничего делать с имуществом, кроме как пометить его значком! , чтобы сообщить транспиллеру, что vue установит переменную за вас.

$store!: Store<StoreStateType>;

Другая альтернатива, которую я использую, - использовать помощники компонентов MapState или MapGetters. Они создают для вас свойства, чтобы вы могли использовать их в шаблоне. Пример:

@Component({
  computed: mapState({
    userFullName: (state: any) => state.user.fullName,
    userEmail: (state: any) => state.user.email
  })
})

Не забудьте импортировать Store, ваш класс состояния vuex и любой помощник, который вы используете import { Store, mapState } from "vuex";.

К сожалению, невозможно переопределить тип Store<any>, который определяется типами VueX, более конкретным типом. Лучшее, что я мог придумать, - это добавить второе поле, которое возвращает $store, но правильно набранное, чтобы вам не приходилось везде использовать приведение типов или объявлять его во всех ваших компонентах:

import { Store } from "vuex";

// Type the $tstore properly, which is the same as $store but properly typed.
// Unfortunately you cannot override the Store<any> type.
declare module "vue/types/vue" {
  interface Vue {
    $tstore: Store<State>;
  }
}

// Set $tstore to be a getter that simply returns $store.
Object.defineProperty(Vue.prototype, "$tstore", {
  get: function() {
    return this.$store as Store<State>;
  },
  enumerable: true,
});
Ответ принят как подходящий

Если кто-то сталкивается с этим - мы обошли эту проблему, переопределив тип, возвращаемый конструктором -

import Vue, { VueConstructor } from 'vue'
import { Store } from 'vuex'
import { RootState } from '@/store/types'

abstract class VueStrongClass extends Vue {
    public $store!: Store<RootState>
}
const VueStrong = Vue as VueConstructor<VueStrongClass>;

export default VueStrong;

а потом мы просто

export default VueStrong.extend({
    name: 'name',

    components: {
        componentA,
        componentB,
},

что позволяет нам правильно печатать:

methods: {
sessionStarted(): Boolean | undefined {
    return this.$store.state.sessionState?.session.started;
},

вы знаете, есть ли способ заставить печатать, чтобы работать с этим. $ store.getters?

maembe 12.09.2020 17:14

@maembe К сожалению, я так не думаю - вы могли бы по-настоящему развлечься с перечислением и некоторыми дженериками, но это хуже, чем просто кастинг вручную. знак равно

user1518267 13.11.2020 21:55

Ни один из ответов меня не удовлетворил. Я покопался и нашел эту жемчужину. Внутри моего файла store.ts я просто добавляю:

declare module "@vue/runtime-core" {
  interface ComponentCustomProperties {
    $store: Store<State>;
  }
}

Так это выглядит примерно так:

//store.ts
import { createStore, Store } from "vuex";
import { CustomTool, CustomListType } from "custom";

export type State = {
  tool: CustomTool
  list: CustomListType | null
};

export default createStore({
  state: {
    tool: CustomTool.Empty
    list: null,
  } as State,
  mutations: {},
  actions: {},
  modules: {}
};

declare module "@vue/runtime-core" {
  interface ComponentCustomProperties {
    $store: Store<State>;
  }
}

Использование vue3 и машинописного текста 4.4.

Другие вопросы по теме