我有很多接口类型,这些接口类型扩展了其他一些“未知”位和嵌套类型,并且我想递归地提取一些我关心的属性。这就是我的想法
//pseudocode
type RecursiveInclude< T, keys> = // implementation here
type A = {
keyToKeep: string
keyToOmit: string
nested: {
keyToKeep: string
keyToOmit: string
foo:string,
nested2:{
keyToKeep: string
keyToOmit: string
}
}
nestedOptional?: {
keyToKeep: string
keyToOmit: string
}
}
// type Result = RecursiveInclude<A, 'keyToKeep' | 'foo' | 'anyotherproperty'>
type Expected = {
keyToKeep: string
nested: {
keyToKeep: string
foo:string,
nested2:{
keyToKeep: string
}
}
nestedOptional?: {
keyToKeep: string
}
}
//任何想法或近似值都欢迎,所以不要害羞
https://stackoverflow.com/users/125734/titian-cernicova-dragomir
给我一些启发,这是他到目前为止所创造的,
唯一需要注意的是,您需要了解所有键,以便可以遍历所有属性 表示您需要提供该类型上的所有键
'keyToKeep' | 'nested' | 'nested2' | 'nestedOptional' | 'foo' | 'anyotherproperty'
更近了,但是最初的问题我无法访问该信息->表示此键
| 'nested' | 'nested2' | 'nestedOptional' |
答案 0 :(得分:1)
这是一种继续进行的方法:
type OmitNever<T> = Omit<T,
{ [K in keyof T]-?: T[K] extends never ? K : never }[keyof T]
>;
type RecursivePick<T extends object, K extends PropertyKey> = OmitNever<{
[P in keyof T]: P extends K ? T[P] : (
T[P] extends infer O ? O extends object ? RecursivePick<O, K> : never : never
)
}> extends infer O ? { [P in keyof O]: O[P] } : never
您可以验证它是否适用于您的类型:
type Result = RecursivePick<A, 'keyToKeep' | 'foo' | 'anyotherproperty'>
/* type Result = {
keyToKeep: string;
nested: {
keyToKeep: string;
foo: string;
nested2: {
keyToKeep: string;
};
};
nestedOptional?: {
keyToKeep: string;
} | undefined;
} */
这里的方法是遍历您的对象并保留每个属性(如果其键在K
中)。如果键是K
中的 not ,请检查该属性是否为对象。如果不是,则要完全忽略该属性。如果是这样,那么您想使用RecursivePick
递归到属性中。
请注意,在使用映射类型进行迭代时,无法省略属性。因此,我将属性设置为never
,然后在结果对象上运行OmitNever<T>
。这样做的副作用是,将消除类型为never
的任何嵌套属性:
type Oops = RecursivePick<{a: never}, "a"> // {}
如果这很重要,我们可以使用其他一些标记来更改RecursivePick
的定义以保留never
属性,但我对此表示怀疑。
答案 1 :(得分:0)
TypeScript仅在这里帮助您进行编译时错误检查。它已编译为JavaScript,并且在运行时不执行任何操作。就像矩阵中的汤匙一样,类型和接口不存在。
创建类型以选择对象中的属性只能在编写代码时帮助您选择那些对象。不会在最终代码中将它们从对象中删除。
如果在编译时无法访问信息,则必须求助于属性,并确保它们通过JavaScript手段存在。您可以创建类型保护,以帮助您做到这一点,同时仍保留一些您知道的类型。