Привет, мне очень нравится идея vuex и глобального хранилища, но я всегда ненавидел использовать мутации, передавая magic-string функции фиксации. Это решение просто напрашивается на опечатку. Поэтому, когда машинописный текст стал популярным, я был очень взволнован тем, что, возможно, кто-то исправит мутации Vuex, чтобы вам не нужно было использовать magic-strings, но, к сожалению, этого не произошло: /

Я решил поставить себе цель создать сервис магазина с действиями, основанными на полностью типизированных мутациях. Итак, я создал простой модуль vuex, который выглядит так:

export const ClientStoreModule = {
  namespaced: false,
  state: new ClientStoreState(),
  getters: {
    clients(state: ClientStoreState) {
      return state.Clients;
    },
  },
  mutations: {
    setClients(state: ClientStoreState, clients: Array<Client>) {
      state.Clients = clients;
    },
    addClient(state: ClientStoreState, client: Client) {
      state.Clients.push(client);
    },
  },
};

А вот и мой государственный класс:

export class ClientStoreState {
  Clients: Array<Client> = [];
}

Моей целью было добиться мутаций, которые можно было бы использовать примерно так:

commit<Client>(ClientStoreModule.mutations.addClient, client);

Итак, я начал с Google эту проблему и нашел отличную библиотеку под названием vuex-typescript, и вот ссылка:



Это классная библиотека, но она заставила вас использовать такие коммиты:

let storeApi = getStoreAccessors<ClientStoreState, RootState>('')
let commit = storeApi.commit(ClientStoreModule.mutations.addClient)
commit(this.$store, client)

Для получения полной документации перейдите по ссылке, которую я разместил выше.

И снова, ладно, это круче, чем старомодно
commit('addClient', client). Теперь у нас есть полностью типизированные мутации! Но это решение длинное, и для его использования требуется много кода. Так что я немного завернул его.

Я создал абстрактный класс, чтобы расширить свой будущий сервис с помощью действий vuex:

import {getStoreAccessors, MutationHandlerWithPayload} from 'vuex-typescript';
export default abstract class BaseStoreService<T> {
  protected mutations!: Record<string,(state: T, payload: any) => void>;
  protected storeApi = getStoreAccessors<T, RootState>('');
  protected commit<TPayload>(handler: (MutationHandlerWithPayload<T, TPayload>), payload: TPayload) {
    this.storeApi.commit(handler)(store, payload);
  }
}

Я использую модули vuex, поэтому мой RootState - это просто интерфейс всего моего магазина vuex.

Хорошо, теперь пора создать службу vuex моей мечты, которая обрабатывает действия:

class ClientStore extends BaseStoreService<ClientStoreState> {
  public mutations = ClientStoreModule.mutations;
  async addClient(newClient: Client) {
    this.commit<Client>(this.mutations.addClient, newClient);
  }
  async fetchClients(clients) {
    this.commit(this.mutations.setClients, clients);
  }
}
export default new ClientStore();

И вот, теперь мы можем использовать нашу полностью типизированную службу с полностью типизированными мутациями, подобными этой ClientStore.addClient(client), и получить отличное автозавершение кода машинописного текста везде, не используя magic-strings где бы то ни было.

Итак, мы хорошо обрабатываем наши мутации, но как насчет getters?

Компонент vue на основе классов, написанный на машинописном тексте, заставляет вас использовать этот синтаксис:

@Getter clients!: Array<Client>;

И снова это не так уж и плохо, но допустим, вы хотите переформатировать переменную клиентов. Вы должны не забывать менять эти имена везде, и это просто беспорядок.

Вернемся в нашу vuex-typescript библиотеку. Так же, как commit , у него есть read функция. Итак, я расширил свой BaseStoreService второй функцией:

import {getStoreAccessors, GetterHandler, MutationHandlerNoPayload, MutationHandlerWithPayload} from 'vuex-typescript';
export default abstract class BaseStoreService<T> {
  protected mutations!: Record<string,(state: T, payload: any) => void>;
  protected storeApi = getStoreAccessors<T, RootState>('');
  protected commit<TPayload>(handler: (MutationHandlerWithPayload<T, TPayload>), payload: TPayload) {
    this.storeApi.commit(handler)(store, payload);
  }
  protected read<TResult>(handler: GetterHandler<T, RootState, TResult>): TResult {
    return this.storeApi.read<TResult>(handler)(store);
  }
}

так что теперь я могу добавить в свой ClientStore метод получения машинописного текста с полной поддержкой машинописного текста и написать свой полностью типизированный получатель следующим образом:

get getClients() {
  return this.read<Array<Client>>(ClientStoreModule.getters.clients)
}

Вот и все, что у нас есть полностью типизированные геттеры и полностью типизированные мутации внутри нашей ClientStore службы, и мы можем получить доступ к нашим геттерам vuex следующим образом:
ClientStore.getClients()