vue.js - Vue Vuex med Typescript Vuex-objekt okänd typ


Jag har problem med att få Vuex att fungera med Typescript. Jag gjorde ett exempel utan Typescript som fungerade helt fint som visas först nedan. Jag skapar en Vuex-modul och lägger sedan till den som visas nedan

src -> store -> index.js

import Vue from 'vue';
import Vuex from 'vuex';
import robotsModule from './modules/products';

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    products: productsModule
  },
});

src -> store -> modules -> products.js

import axios from 'axios';

export default {
  namespaced: true,
  state: {
    products: [],
  },
  mutations: {
    addProduct(state, product) {
      state.products.push(product);
    },
    updateProduct(state, products) {
      state.parts = products;
    },
  },
  actions: {
    getProducts({ commit }) {
      axios
        .get('/api/products')
        .then(result => commit('updateProduct', result.data))
        .catch(console.error);
    }
  },
};

Nu när jag vill använda TypeScript fortsätter det att klaga på att

"Bindningselementet 'commit' har implicit typen 'any'."

Som du kan se har jag för närvarande angett staten som any, vilket också verkar fel. Hur får jag detta att fungera bra med TypeScript?

src -> store -> modules -> products.ts

import axios from 'axios';
import { Product } from '@/models/product';

export default {
  namespaced: true,
  state: {
    products: new Array<Product>(),
  },
  mutations: {
    updateProducts(state: any, products: Product[]) {
      state.products = products;
    },
    addProduct(state: any, product: Product) {
      state.products.push(product);
    },
  },
  actions: {
    getProducts({ commit }) {
      axios
        .get('/api/products')
        .then(result => commit('updateProducts', result.data))
        .catch(console.error);
    },
  },
};

Svar #1

Jag hittade ett exempel online som visade att jag behövde ha commiten som en funktion

getProducts({ commit }: { commit: Function }) {

fullständig fil här

import axios from 'axios';

import { Product } from '@/models/product';
import State from '@/models/state';

export default {
  namespaced: true,
  state: {
    items: new Array<Product>(),
  } as State,
  mutations: {
    updateProducts(state: State, products: Product[]) {
      state.items = products;
    },
    addProduct(state: State, product: Product) {
      state.items.push(product);
    },
  },
  actions: {
    getProducts({ commit }: { commit: Function }) {
      axios
        .get('/api/products')
        .then(result => {
          commit('updateProducts', result.data);
        })
        .catch(console.error);
    },
  },
};

Skapa också en State-klass som jag sedan kan säga är mitt state-objekt

import Vue from 'vue';
import { Product } from '@/models/product';

export default class State extends Vue {
  items: Product[] = new Array<Product>();
}

Uppdatering 15-03-2021 - En arbetskollega till mig sa att han nu använder https://www.npmjs.com/package/direct-vuex vilket gör det enklare!

Svar #2

Bygger vidare på Andrews svar - du kan införa ett par gränssnitt för att städa upp koden lite:

export interface CommitFunction {
    commit: Commit;
}

export interface CommitStateFunction<T> extends CommitFunction {
    state: T;
}

Så skulle din handling se ut:

actions: {
    getProducts({ commit }: CommitFunction) { /* logic here */ },
    updateProducts({ commit, state }: CommitStateFunction<State>) { /* logic here */ }
}

Relaterade artiklar