Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.3k views
in Technique[技术] by (71.8m points)

typescript - Why can't these generic type be inferred?

I'm writing a Vuex store for Vue 3, and the following issue has been bother me recently.

Please consider following minimal reproducible example:

interface Options<State, G extends Getters<State>> {
  state: State
  getters: G,
  mutations: {
    [P: string]: (state: State, getters: G) => void
  }
}

interface Getters<State> {
  [P: string]: (state: State) => any
}

function createStore<State>(options: Options<State, Getters<State>>) {
  return options
}

createStore({
  state: {
    count: 0
  },
  getters: {
    isOdd: (state) => state.count % 2 === 1
  },
  mutations: {
    incrementIfOdd (state, getters) {
      if (getters.isOdd) {
               // ^ a this cannot be inferred to Boolean here.
        ++state.count
               // ^ ok, it is number.[enter image description here][1]
      }
    }
  }
})

Codesandbox IDE snapshot

Further code info can be found here: https://github.com/js-cosmos/vuex-light/issues/11

Thanks for your help :D.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This is because you're using P: string for your mutations and getters, so we don't know what the specific keys are, and therefore their types can be inferred.

You should use extra generic parameters for P here - for the MutationKeys and GetterKeys, which can then be inferred correctly:

interface Options<
  State,
  MutationKeys extends string,
  G extends Getters<State, string>
> {
  state: State;
  getters: G;
  mutations: {
    [P in MutationKeys]: (state: State, getters: G) => void;
  };
}

type Getters<State, Keys extends string> = {
  [key in Keys]: (state: State) => any;
};

function createStore<
  State,
  MutationKeys extends string,
  GetterKeys extends string
>(options: Options<State, MutationKeys, Getters<State, GetterKeys>>) {
  return options;
}

createStore({
  state: {
    count: 0
  },
  getters: {
    isOdd: (state) => state.count % 2 === 1
  },
  mutations: {
    incrementIfOdd(state, getters) {
      if (getters.isOdd(state)) {
        ++state.count;
      }
    }
  }
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...