Вывод структуры объекта и типа свойств объекта

Мне нужно вывести структуру и свойства объекта из результата, возвращаемого функцией.

Когда функция возвращается, мне нужна та же структура, которую я добавил, но свойства этих ключей должны быть определенных type или interface.

interface Validated{
    error:boolean
    missing:boolean
    validated:boolean
}

interface Result<T>{
    error:boolean,
    struct:T
}

const testObj ={
    d1:{
        d2:{
            name:'jack'
        }
    }
}

function test<T>(obj:T):Result<T>{
    return {
        error: false,
        struct: {
            d1: {
                d2: {
                    name: {
                        error: false,
                        missing: false,
                        validated: true
                    }
                }
            }
        }
    };
}

const result = test(testObj)

//result.struct.d1.d2.name // works

// result.struct.d1.d1.name.validated // does not work



Когда функция возвращает результат, я могу просмотреть структуру, которую передал функции result.d1.d2.name

Однако мне нужно, чтобы свойство name выводилось как Validated интерфейс result.d1.d2.name.validated

Итак, вопрос в том, как подключить интерфейс Validated к свойству name, независимо от глубины свойства.

TS площадка


person Ivan V.    schedule 31.08.2019    source источник


Ответы (2)


Рекурсивное использование типа в сочетании с условным выражением должно помочь:

type DeepValidated<T> = T extends object
    ? { [K in keyof T]: DeepValidated<T[K]> }
    : Validated

interface Result<T>{
    error:boolean,
    struct:DeepValidated<T>
}

DeepValidated проверяет, является ли T объектом. В этом случае он перебирает все свойства и применяется DeepValidated рекурсивно. В противном случае он возвращает Validated, эффективно заменяя исходный тип T.

площадка

person lukasgeiter    schedule 31.08.2019

Я понимаю, что вы хотите, чтобы свойство с желаемым именем заменило его тип значения, независимо от глубины объекта.

Это решение:

/**
 * From object O,
 * Replace the value type of keys KV,
 * By the type V
 */
type ReplaceType<O extends object, KV, V> = {
    [K in keyof O]: K extends KV ? V : (
        O[K] extends object ? ReplaceType<O[K], KV, V> : O[K]
    );
};

interface Result<T extends object>{
    error: boolean,
    struct: ReplaceType<T, 'name', Validated>;
}

Разница с ответом @lukasgeiter в том, что я меняю только нужное поле, остальные остаются без изменений.

person Richard Haddad    schedule 31.08.2019
comment
Я должен был прояснить, что свойство name - всего лишь пример. Собираются произвольное количество свойств. - person Ivan V.; 31.08.2019