来自对象的所有嵌套值的类型

时间:2020-04-24 19:35:17

标签: typescript

我想知道是否有更好的方法来获取对象的所有嵌套值类型。我的情况尤其可以概括为这种情况:

const myObj = {
    group1: {
        subGroup11: () => {return {} as const},
        subgroup12: () => {return {} as const},
        ...
    },
    group2: {
        subGroup21: () => {return {} as const},
        subGroup22: () => {return {} as const},
        ...
    }
    ...
}

所有最终值都是函数。

我目前正在做的事情是详尽无遗的,所以我从每个嵌套属性中获取所有类型:

type myType = <ReturnType
   typeof myObj.group1.subGroup12 |
   typeof myObj.group1.subGroup22 |
   ...
   typeof myObj.group2.subGroup21 |
   ...
>

注意:

  1. 属性名称的索引符号只是为了示例。

  2. 组不一定具有相同的属性。

更新答案:

查看Maciej'sleonard's的答案,因为它们绝对正确。后一种方法检查的对象类型最多可达2个深度,而第一种方法则递归地应用于任何深度,还请注意,即使值不是函数,此最后一个解决方案也可以使用。谢谢Maciej,leonard和jcalz的贡献。

2 个答案:

答案 0 :(得分:1)

您应该结合使用映射类型,推断和伪递归。沿T[K][keyof T[K]]行的东西,不仅使用推论来获取R(返回类型),而且甚至查找级别1的属性是函数还是级别2(“组”对象),例如:

type FlattenTwoLevels<T extends {}> = {
    [K in keyof T]: T[K] extends (...args: any) => any ? T[K] : T[K][keyof T[K]]
}[keyof T];

type ReturnMyObj = ReturnType<FlattenTwoLevels<typeof myObj>>;

我省略了(...args: any) => infer R的推论,因为默认情况下ReturnType在这里已经可以使用,因此FlattenTwoLevels泛型助手仅需要{{1} }。

这里是Playground Link

答案 1 :(得分:1)

我们可以创建一个通用类型,该通用类型适用于任何嵌套结构。在这里

type SelectFunctionRetunTypes<T extends object> =
    {
        [K in keyof T]
        : T[K] extends (...args: any) => any
        ? ReturnType<T[K]>
        : T[K] extends object
            ? SelectFunctionRetunTypes<T[K]>
            : T[K] // primary value not a function and not an object  
    }[keyof T]

type ReturnsMyObj = SelectFunctionRetunTypes<typeof myObj>;

SelectFunctionRetunTypes是递归类型,当我们的值T[K]是函数类型时,我们通过ReturnType类型级别的函数从中获取返回类型,如果它不是函数,则检查其是否为对象,如果是,则通过递归调用SelectFunctionRetunTypes在此对象中继续相同的算法。最后一部分是当它不是函数而不是对象时,在这种情况下,我们只返回我们拥有的值的类型。

此泛型类型可用于所有类型的嵌套对象类型,如果值类型是函数,它将提供返回类型,否则将返回值类型。

The Playground

中的完整示例