推断对象结构和对象属性类型

时间:2019-08-31 16:53:06

标签: typescript typescript-typings

我需要从函数的返回结果推断对象的结构和属性。

当函数返回时,我需要使用与输入相同的结构,但是这些键上的属性必须具有特定的typeinterface

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 playground

2 个答案:

答案 0 :(得分:1)

以递归方式将类型与条件结合使用将达到目的:

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

Playground

答案 1 :(得分:0)

我了解到,无论对象的深度如何,您都希望使用所需名称的属性来替换其值类型。

这是一个解决方案:

/**
 * 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答案的区别在于,我仅更改了所需字段,其他字段保持不变。