vuex-typescript-interface
vuex-typescript-interface copied to clipboard
Type inference with generics
Hey, thanks for your awesome lib!
When using generics in mutations (and actions too), lookup types are not inferred as accurately as they could be.
Here is my store definition:
import { Module, MutationTree } from 'vuex-typescript-interface';
interface Filters {
search: string;
toggleThing: boolean;
}
interface FiltersModule {
filters: Filters,
UPDATE_FILTERS<T extends keyof Filters>(payload: { key: T, value: Filters[T] }): void;
}
const mutations: MutationTree<FiltersModule> = {
UPDATE_FILTERS: (state, {key, value}) => {
state.filters = {
...state.filters,
[key]: value
};
}
}
const module: Module<FiltersModule, RootState> = {
state: {
filters: {
search: '',
toggleThing: false
}
},
mutations: mutations
}
export default module;
And when I use the mutation in a component:
store.commit('UPDATE_FILTERS', { key: 'search', value: 'foo' }) // Working, as expected
store.commit('UPDATE_FILTERS', { key: 'search', value: 4 }) // Fail, of course
store.commit('UPDATE_FILTERS', { key: 'search', value: true }) // Does not fail even if it should 😞
It seems that the union of all possible types is inferred, so here value
can be string
or boolean
, instead of being specific to the key used.
But TypeScript should be able to handle this situation correctly. It does work with a standard function:
interface Filters {
search: string;
toggleThing: boolean;
}
function test<T extends keyof Filters>(payload: { key: T, value: Filters[T] }): void {
// Do nothing
}
test({ key: 'search', value: 'foo' }) // Ok
test({ key: 'search', value: 4 }) // Fail
test({ key: 'search', value: true }) // Fail too
Is it something that can be improved? :slightly_smiling_face:
I'll look into it as I work on the new version for Vuex 4