DEV Community

Discussion on: Vuex + TypeScript

Collapse
 
mat813 profile image
Mathieu Arnold • Edited

So, I was applying all the wisdom in here, to my quite large vuex stack, and I stumbled upon the second argument of Getters (I leave the third and fourth to the reader)

Basically, the second argument to Getters references the Getters for the current namespace, but not as functions, as values directly.

For example, I have this:

export type Getters = {
  user(state: State): PayloadUser | {};
  roles(state: State, getters: any): string[];
  isAdmin(state: State, getters: any): boolean;
};

export const getters: GetterTree<State, State> & Getters = {
  user({ token }) {
    if ('user' in token) {
      return token.user;
    } else {
      return {};
    }
  },
  roles(_, getters) {
    if ('roles' in getters.user) {
      return getters.user.roles;
    } else {
      return [];
    }
  },
  isAdmin(_, getters) {
    return getters.roles.includes('admin');
  },
Enter fullscreen mode Exit fullscreen mode

The problem is that the getters argument as an "any" type everywhere, I tried to put the Getters type, but that was not right. After a bit of fiddeling around (I am still a bit new and rough in typescript) I ended up having this :

export type SubGetters<T extends { [K in keyof T]: (...any: any[]) => any }> = {
  [K in keyof T]: ReturnType<T[K]>;
};

export type Getters = {
  user(state: State, getters: SubGetters<Getters>): PayloadUser | {};
  roles(state: State, getters: SubGetters<Getters>): string[];
  isAdmin(state: State, getters: SubGetters<Getters>): boolean;
};
Enter fullscreen mode Exit fullscreen mode

The naming is probably awful, and now that I think about it, one should just have to generate a Getters that is, say, user: PayloadUser; roles: string[]; and a different kind of fiddeling be done so that the type with the function definitions can be generated automatically.

Also, if all this goes into a module somewhere, this should probably get there too.

Collapse
 
mat813 profile image
Mathieu Arnold

So, I thought about what I wrote in the end and changed my code, it now reads:

export type FunGetters<T extends { [K in keyof T]: any }> = {
  [K in keyof T]: (state: State, getters: Getters) => T[K];
};

export type Getters = {
  loggedIn: boolean;
  expirationTime: number;
  user: PayloadUser | {};
  roles: string[];
  isAdmin: boolean;
};

export const getters: GetterTree<State, State> & FunGetters<Getters> = {
// [...]
Enter fullscreen mode Exit fullscreen mode