And*_*Los 4 recursion types typescript
我想编写一个递归省略字段的类型实用程序。你会这样命名和使用的东西OmitRecursively<SomeType, 'keyToOmit'>
我尝试使用映射类型 + 条件类型来完成它,但是当所有必需的字段都正确输入时我坚持了这种情况(因此字段从嵌套类型中消失了),但是该方法忽略了可选字段。
// This is for one function that removes recursively __typename field
// that Appolo client adds
type Deapolify<T extends { __typename: string }> = Omit<
{ [P in keyof T]: T[P] extends { __typename: string } ? Deapolify<T[P]> : T[P] },
'__typename'
>
// Or more generic attempt
type OmitRecursively<T extends any, K extends keyof T> = Omit<
{ [P in keyof T]: T[P] extends any ? Omit<T[P], K> : never },
K
>
Run Code Online (Sandbox Code Playgroud)
预期行为将是 root,并且所有嵌套键的类型都应递归省略。例如
// This is for one function that removes recursively __typename field
// that Appolo client adds
type Deapolify<T extends { __typename: string }> = Omit<
{ [P in keyof T]: T[P] extends { __typename: string } ? Deapolify<T[P]> : T[P] },
'__typename'
>
// Or more generic attempt
type OmitRecursively<T extends any, K extends keyof T> = Omit<
{ [P in keyof T]: T[P] extends any ? Omit<T[P], K> : never },
K
>
Run Code Online (Sandbox Code Playgroud)
Tit*_*mir 10
你不OmitRecursevly
递归调用,如果属性类型是一个对象,我也只会递归应用省略,否则它应该主要工作:
type OmitDistributive<T, K extends PropertyKey> = T extends any ? (T extends object ? Id<OmitRecursively<T, K>> : T) : never;
type Id<T> = {} & { [P in keyof T] : T[P]} // Cosmetic use only makes the tooltips expad the type can be removed
type OmitRecursively<T extends any, K extends PropertyKey> = Omit<
{ [P in keyof T]: OmitDistributive<T[P], K> },
K
>
type A = {
keyToKeep: string
keyToOmit: string
nested: {
keyToKeep: string
keyToOmit: string
}
nestedOptional?: {
keyToKeep: string
keyToOmit: string
}
}
type Result = OmitRecursively<A, 'keyToOmit'>
Run Code Online (Sandbox Code Playgroud)
编辑:更新以反映添加的内置Omit
助手类型。对于旧版本,只需定义 Omit。
Note Id
主要用于外观原因(它强制编译器Pick
在工具提示中扩展)并且可以删除,它有时会在某些核心情况下导致问题。
编辑
原始代码不起作用,strictNullChecks
因为属性的类型是type | undefined
. 我编辑了代码以分发到工会。条件类型OmitDistributive
用于其分配行为(我们出于这个原因而不是条件使用它)。这意味着OmitRecursively
将应用于工会的每个成员。
说明
默认情况下,该Omit
类型在联合上不能很好地工作。Omit
将联合视为一个整体,不会从联合的每个成员中提取属性。这主要是因为它keyof
只会返回联合的公共属性(keyof undefined | { a: number }
实际上也是如此never
,因为没有公共属性)。
幸运的是,有一种方法可以使用条件类型来钻取联合。条件类型将分布在裸类型参数上(请参阅此处了解我的解释或文档)。在OmitDistributive
我们并不真正关心条件(这就是我们使用T extends any
)的情况下,我们只关心如果我们使用条件类型T
将依次成为联合中的每个成员。
这意味着这些类型是等效的:
OmitDistributive<{ a: number, b: number} | undefined}, 'a'> =
OmitRecursively<{ a: number, b: number}, 'a'> | undefined
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1745 次 |
最近记录: |