我需要从函数的返回结果推断对象的结构和属性。
当函数返回时,我需要使用与输入相同的结构,但是这些键上的属性必须具有特定的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
属性。
答案 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
。
答案 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答案的区别在于,我仅更改了所需字段,其他字段保持不变。