繁体   English   中英

为什么不能推断出这些泛型类型?

[英]Why can't these generic type be inferred?

我正在为 Vue 3 编写一个 Vuex 商店,最近以下问题一直困扰着我。

请考虑以下最小的可重现示例:

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 快照

更多代码信息可以在这里找到: https://github.com/js-cosmos/vuex-light/issues/11

感谢您的帮助:D。


更新:

我尝试删除包装选项并且它有效!

为了简化示例代码:

 // This works function spreadOptionsFn< State extends Record<any, any>, Getters extends Record<any, ({ state }: { state: State }) => any>, Mutations extends Record<any, ({ state, getters }: { state: State; getters: Getters }) => any> >(state: State, getters: Getters, mutations: Mutations) {} spreadOptionsFn( { stateKey: 'state' }, { getterKey: ({ state }) => state.stateKey }, { mutationKey: ({ state, getters }) => [state.stateKey, getters.getterKey] }, ) // But not this function wrappedOptionsFn< State extends Record<any, any>, Getters extends Record<any, ({ state }: { state: State }) => any>, Mutations extends Record<any, ({ state, getters }: { state: State; getters: Getters }) => any> >({ state, getters, mutations }: { state: State; getters: Getters; mutations: Mutations }) {} wrappedOptionsFn({ state: { stateKey: 'state' }, getters: { getterKey: ({ state }) => state.stateKey }, mutations: { mutationKey: ({ state, getters }) => [state.stateKey, getters.getterKey] }, })

用于类型推断的CodeSandbox屏幕截图


更新 2:

我又错过了一些东西,最后用以下代码修复:


interface Options<
  State extends Record<any, any>,
  GetterKeys extends string,
  MutationKeys extends string,
> {
  state: State,
  getters: {
    [P in GetterKeys]: ({ state }: { state: State }) => any
  },
  mutations: {
    [P in MutationKeys]: ({ state, getters }: { state: State; getters: {
      [P in GetterKeys]: ({ state }: { state: State }) => any
    } }) => any
  },
}

function wrappedOptionsFn<
  State extends Record<any, any>,
  GetterKeys extends string,
  MutationKeys extends string,
>(options: Options<State, GetterKeys, MutationKeys>) {
}

wrappedOptionsFn({
  state: { stateKey: 'state' },
  getters: { getterKey: ({ state }) => state.stateKey },
  mutations: { mutationKey: ({ state, getters }) => [state.stateKey, getters.getterKey] },
})

这是因为您使用 P: 字符串作为突变和吸气剂,所以我们不知道具体的键是什么,因此可以推断出它们的类型。

您应该在这里为 P 使用额外的通用参数 - 对于 MutationKeys 和 GetterKeys,然后可以正确推断:

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;
      }
    }
  }
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM