Hai, Saya sangat menyukai ide vuex dan memiliki penyimpanan global, tapi saya selalu benci menggunakan mutasi dengan meneruskan magic-string ke fungsi komit. Solusi ini hanya menimbulkan kesalahan ketik. Jadi ketika skrip ketikan menjadi populer, saya sangat bersemangat karena mungkin seseorang akan memperbaiki mutasi Vuex sehingga Anda tidak perlu menggunakan magic-strings, tapi sayangnya, hal itu tidak terjadi :/

Saya telah memutuskan untuk menetapkan tujuan untuk membuat layanan toko dengan tindakan yang didasarkan pada mutasi yang diketik sepenuhnya. Jadi saya membuat modul vuex sederhana yang terlihat seperti ini:

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);
    },
  },
};

Dan inilah kelas negara bagian saya:

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

Tujuan saya adalah mencapai mutasi yang dapat digunakan kurang lebih seperti ini:

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

Jadi saya memulai dari Google masalah ini dan saya menemukan perpustakaan hebat bernama vuex-typescript dan ini tautannya:



Perpustakaan ini keren tetapi memaksa Anda untuk menggunakan komitmen Anda seperti ini:

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

Untuk dokumentasi lengkap, buka tautan yang saya letakkan di atas

Dan sekali lagi, oke, ini lebih keren dari mode lama
commit('addClient', client). Sekarang mutasi kita sudah terketik sepenuhnya! Namun solusi ini hanya memakan waktu lama dan memerlukan banyak kode untuk menggunakannya. Jadi saya membungkusnya sedikit.

Saya membuat kelas abstrak untuk memperluas layanan masa depan saya dengan tindakan 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);
  }
}

Saya menggunakan modul vuex jadi RootState saya hanyalah antarmuka dari seluruh toko vuex saya.

Oke sekarang saatnya membuat layanan vuex impian saya yang menangani tindakan:

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();

Dan ini dia sekarang kita dapat menggunakan layanan yang diketik sepenuhnya dengan mutasi yang diketik sepenuhnya seperti ini ClientStore.addClient(client) dan mendapatkan penyelesaian kode yang bagus ketikan di mana saja tanpa menggunakan magic-strings di mana pun.

Oke, jadi kita menangani mutasi kita dengan cara yang baik ini, tapi bagaimana dengan getters?

Komponen vue berbasis kelas yang ditulis dalam skrip ketikan memaksa Anda untuk menggunakan sintaksis ini:

@Getter clients!: Array<Client>;

Dan sekali lagi ini tidak terlalu buruk, tapi katakanlah Anda ingin memformat ulang variabel klien Anda. Anda harus ingat untuk mengubah nama-nama ini di mana-mana dan itu hanya akan berantakan.

Mari kita kembali ke perpustakaan vuex-typescript kita. Sama seperti commit ia memiliki fungsi read. Jadi saya memperluas BaseStoreService saya dengan fungsi kedua:

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);
  }
}

jadi sekarang saya dapat menambahkan pengambil skrip ketikan ClientStore saya dengan dukungan skrip ketikan sepenuhnya dan menulis pengambil yang diketik sepenuhnya seperti ini:

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

dan hanya itu yang kita miliki adalah pengambil yang diketik sepenuhnya dan mutasi yang diketik sepenuhnya di dalam layanan ClientStore kita dan kita dapat mengakses pengambil vuex seperti ini:
ClientStore.getClients()