Типы из всех вложенных значений объекта - PullRequest
1 голос
/ 24 апреля 2020

Интересно, есть ли лучший способ получить все типы вложенных значений объекта. Мой случай, в частности, может быть обобщен на что-то вроде этого:

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's * Ответы 1026 * и Леонарда , так как они абсолютно точны. Последний подход проверяет типы объектов глубиной до 2 уровней, в то время как первый работает рекурсивно на любую глубину, также обратите внимание, что последнее решение работает, даже если значения не являются функциями. Спасибо Maciej, Леонард и Jcalz за вклад.

Ответы [ 2 ]

1 голос
/ 25 апреля 2020

Мы можем создать обобщенный тип c, который будет работать с любой вложенной структурой. Здесь это

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. Последняя часть - это когда это не функция и не объект, в этом случае мы просто возвращаем тип значения, который у нас есть.

Этот обобщенный тип c при работе со всеми типами вложенных типов объектов, он даст тип возврата, если тип значения - функция, и просто тип значения, если нет.

Полный пример в Игровая площадка

1 голос
/ 25 апреля 2020

Вы должны использовать комбинацию отображенных типов, логического вывода и поддельной рекурсии. Что-то по линии 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 generi c нужно только сделать объект доступным для использования ReturnType.

Вот ссылка Playground

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...