fny
fny

Reputation: 33635

Self-referential Type in TypeScript

I currently have an object similar to the following in a Vue.js app that I'm trying to port over to TypeScript. Note this object's structure is dictated by the Vuex library:

const getters = {
  allUsers(state) {
    return state.users;
  },
  firstUser(_state, getters) {
    return getters.allUsers()[0]
  }
}

How can I provide the appropriate type for getters here in firstUser?

const getters = {
  allUsers(state: State) {
    return state.users;
  },
  firstUser(_state: State, getters: typeof getters) {
    return getters.allUsers()[0]
  }
}

Currently I get the following error:

[ts] 'getters' is referenced directly or indirectly in its own type annotation.

Update: @basarat determined you can make that error go away by renaming the argument.

const getters = {
  allUsers(state: State) {
    return state.users;
  },
  firstUser(_state: State, theGetters: typeof getters) {
    return theGetters.allUsers()[0]
  }
}

However, typeof getters ends up being any rather than the type of the getters object.

Upvotes: 3

Views: 1579

Answers (2)

jcalz
jcalz

Reputation: 330571

I really can't understand why you need getters to act this way, but I'll presume you know what you're doing.

This is a limitation of the TypeScript compiler: it will realize that the type of getters is recursive, and gives it an any type. The only way around this is to have a type name for getters and use it. How about a class?

class Getters {
  allUsers(state: State) {
    return state.users;
  }
  firstUser(_state: State, theGetters: Getters) {
    return theGetters.allUsers()[0]; // hey, a bug!
  }
}
const getters = new Getters();

This now is properly typed, and even shows you a bug in your implementation of firstUser (which you fix by, I guess, passing _state into allUsers()).

Hope that helps. Good luck.

Upvotes: 2

basarat
basarat

Reputation: 276393

[ts] 'getters' is referenced directly or indirectly in its own type annotation.

There are two getters in scope. The parameter and the variable. Change one.

Fixed

const getters = {
  allUsers(state: State) {
    return state.users;
  },
  firstUser(_state: State, _getters: typeof getters) { // Rename
    return _getters.allUsers()[0]
  }
}

More

There are other errors, but this is the one you are asked help for.

Upvotes: 2

Related Questions