ClickerMonkey / vuex-typescript-interface

Adding magical type safety to Vuex without additional code
MIT License
44 stars 4 forks source link

Subsequent property declarations must have the same type. Property 'store' must be of type 'Store<any>', but here has type 'Store<any>'. #5

Closed blackmad closed 5 years ago

blackmad commented 5 years ago

No idea why I'm getting this error from deep inside the library

ERROR in /Users/blackmad/Dropbox/Code/mixlet/node_modules/vuex-typescript-interface/vue.d.ts
13:5 Subsequent property declarations must have the same type.  Property 'store' must be of type 'Store<any>', but here has type 'Store<any>'.
    11 |   interface ComponentOptions<V extends Vue> 
    12 |   {
  > 13 |     store?: Store<any>;
       |     ^
    14 |   }
    15 | 
    16 | }

my store.ts looks like this

import Vue from 'vue';
import Vuex from 'vuex-typescript-interface';

import router from '@/router';

import * as fb from './firebase';

Vue.use(Vuex);

interface IStore
{
  // State (are non-function properties not marked readonly)
  currentUser: any;
  loginRedirect: string | null;
  userProfile: any;

  // Getters
  readonly isLoggedIn: boolean;

  // Mutations (functions return void and optionally accept payload)
  setCurrentUserMutation(val: any): void;
  setLoginRedirect(val: string | null): void;
  setUserProfileMutation(val: any): void;

  // Actions (functions return Promise and optionally accept payload)
  setCurrentUser (val: firebase.User | null): Promise<void>;
  setUserProfile (val: any): Promise<void>;
}

const store = new Vuex.Store<IStore>({
  state: {
    currentUser: null,
    loginRedirect: null,
    userProfile: null
  },
  getters: {
    isLoggedIn(state, getters, rootState, rootGetters): boolean {
      return !!state.userProfile;
    }
  },
  mutations: {
    setCurrentUserMutation(state, val) {
        state.currentUser = val;
    },
    setLoginRedirect(state, val) {
      state.loginRedirect = val;
    },
    setUserProfileMutation(state, val) {
      state.userProfile = val;
    },
  },
  actions: {
    async setCurrentUser({ commit, state }, currentUser: firebase.User | null | undefined) {
      if (currentUser) {
        fb.usersCollection.doc(currentUser.uid).get().then((res) => {
          if (!res.exists) {
            router.push('/create_profile')
          } else {
            store.dispatch('setUserProfile', res.data())
          }
        }).catch(err => {
            console.log(err)
        })
      } else {
        commit('setUserProfileMutation', null);
      }
    },

    async setUserProfile({ commit, state }, val) {
      commit('setCurrentUserMutation', val);
      const redirect = state.loginRedirect;
      if (redirect) {
        commit('setLoginRedirect', null);
        router.push(redirect);
      }
    }
  }
});

export default store;
ClickerMonkey commented 5 years ago

I would remove the dependency for vuex and just use vuex-typescript-interface. The vuex types interfere. This library supplies the vuex functionality but with better type support.

mrkswrnr commented 5 years ago

While your workaround works for projects where vuex has been installed directly as a dependency, it does not work for e. g. nuxt.js which depends on vuex itself.

Is there anything we can do until microsoft/TypeScript#18588 has landed 🙁?

ClickerMonkey commented 5 years ago

@mrkswrnr The workaround last time I had this problem was to cast your store to unknown then cast it to the Vuex store. Something like this:

import { mystore } from './mystore';
import { Store } from 'vuex';

new Vue({
  store: mystore as unknown as Store
});
mrkswrnr commented 5 years ago

Thanks for your response!

The problem with Nuxt is that stores are not created directly but by convention. Every .js/.ts file inside the store directory is transformed as a namespaced module (index being the root module) (see: Vuex Store - Nuxt.js).

Therefore there is no real store initialisation written by the user. Your definition of vue.d.ts collides with Vuex's vue.d.ts which is required by Nuxt.js.

My only workaround for the moment was to fork your project and exclude the vue.d.ts, loosing the possibility to use the type store easily.