I wrote this with a generic Drop
instead of just a literal string "remove"
but we can set a default value for Drop
as "remove"
.
type Removed<T, Drop = "remove"> = T extends object ? {
[K in Exclude<keyof T, Drop>]: Removed<T[K], Drop>
} : T;
T
represents the entire value. At each level of the object, we want to only keep the keys which are not assignable to our Drop
key generic: Exclude<keyof T, Drop>
. To apply this recursively, the new value for that key must itself be filtered: Removed<T[K], Drop>
. The T extends object ? {...} : T;
is not actually necessary, but leads to cleaner inferred types.
Typescript Playground Link
This checks out with your sample input and output. Applying the type to your function is a mess though.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…