将第二个功能参数的Typescript类型定义为作为第一个功能参数传入的keyof对象

时间:2019-06-17 01:03:10

标签: typescript

背景

假设我有这个对象:

const state = {
  sideMenu: {
    isOpen: false,
    foo: "bar"
  },
  foo: "bar"
};

我还有一个将state.sideMenu.isOpen更改为true的功能。

dispatch(changeStateBoolean("sideMenu", "isOpen", true));

忽略dispatch()函数,因为该函数与该问题无关。 changeStateBoolean()返回dispatch()用于更新状态的对象。

问题

如何将第二个参数(在这种情况下为"isOpen")的类型设置为第一个参数(在这种情况下为"sideMenu")的键?

代码

这是我到目前为止所拥有的:

interface ChangeState<T> {
  (
    state: keyof State,
    key: keyof State[*** NEED HELP HERE ***],
    value: T
  ): ChangeStateReturn<T>;
}

interface ChangeStateReturn<T> {
  type: T extends boolean
    ? typeof CHANGE_STATE_BOOLEAN
    : T extends number
    ? typeof CHANGE_STATE_NUMBER
    : typeof CHANGE_STATE_STRING;
  payload: {
    state: keyof State;
    key: keyof State["*** NEED HELP HERE ***];
    value: T;
  };
}

export const changeStateBoolean: ChangeState<boolean> = (state, key, value) => {
  return {
    type: CHANGE_STATE_BOOLEAN,
    payload: {
      state,
      key,
      value
    }
  };
};

1 个答案:

答案 0 :(得分:0)

这应该有效。 您需要使用泛型来访问类型。

出于示例目的,我更改了您的代码(例如删除CHANGE_STATE_BOOLEAN)。

const state = {
    sideMenu: {
        isOpen: false,
        foo: "bar"
    },
    foo: "bar"
};

type ChangeState<
    S,
    V,
    T extends keyof S = keyof S,
    K extends keyof S[T] = keyof S[T]
    > = {
        (state: T, key: K, value: V): ChangeStateReturn<S, V, T, K>;
    }

type ChangeStateReturn<
    S,
    V,
    T extends keyof S = keyof S,
    K extends keyof S[T] = keyof S[T]
    > = {
        type: V extends boolean ? boolean : V extends number ? number : string;
        payload: {
            state: T;
            key: K;
            value: V;
        };
    }

export const changeStateBoolean: ChangeState<typeof state, boolean> = (stateName, key, value) => {
    return {
        type: true,
        payload: {
            state: stateName,
            key,
            value
        }
    };
};