【问题标题】:Define Typescript type of second function parameter as the keyof object that was passed in as first function parameter将第二个函数参数的 Typescript 类型定义为作为第一个函数参数传入的 keyof 对象
【发布时间】:2019-06-17 01:03:10
【问题描述】:

背景

假设我有这个对象:

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

我还有一个函数可以将state.sideMenu.isOpen 更改为true

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

忽略dispatch() 函数,因为它与此问题无关。 changeStateBoolean() 返回一个对象,dispatch() 使用该对象更新状态。

问题

如何将第二个参数(本例中为"isOpen")的类型设置为第一个参数(本例中为"sideMenu")的key?

代码

这是我目前所拥有的:

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

【问题讨论】:

  • 您应该考虑将此代码编辑为minimal reproducible example,其中唯一的问题是您要解决的问题。这意味着任何不能在独立 IDE 中编译的代码都应该被删除或删除。在这种情况下,答案是让你的函数在多个参数中通用……第一个应该是K extends keyof State类型,第二个应该是P extends keyof State[K],然后你可以用@替换T 987654338@。我会准确地给你代码,但是我需要做太多的编辑才能得到一些没有错误的东西。
  • @jcalz 您的示例有效,但我需要将定义放入可以导出的接口或类型中。我尝试重构您的代码,这与下面工会的答案基本相同,但由于某种原因将“键”和“值”设置为never,因此失败并出现错误。有什么想法吗?

标签: typescript


【解决方案1】:

这应该可以。 您需要使用泛型来访问这些类型。

出于示例目的(例如删除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
        }
    };
};

【讨论】:

  • 这不起作用,因为它将key 类型设置为“从不”。
猜你喜欢
  • 2019-11-25
  • 2021-12-20
  • 2023-02-13
  • 1970-01-01
  • 2020-10-21
  • 2023-02-06
  • 2019-05-15
  • 1970-01-01
  • 2011-03-08
相关资源
最近更新 更多