DeepExclude
Sometimes you just want to remove a type from all keys. A DeepExclude would be useful, something like:
type DeepExclude<T, I> = T extends Builtin
? Exclude<T, I>
: T extends Map<infer K, infer V>
? Map<DeepExclude<K, I>, DeepExclude<V, I>>
: T extends WeakMap<infer K, infer V>
? WeakMap<DeepExclude<K, I>, DeepExclude<V, I>>
: T extends Set<infer U>
? Set<DeepExclude<U, I>>
: T extends WeakSet<infer U>
? WeakSet<DeepExclude<U, I>>
: T extends Array<infer U>
? T extends IsTuple<T>
? { [K in keyof T]: DeepExclude<T[K], I> }
: Array<DeepExclude<U, I>>
: T extends Promise<infer U>
? Promise<DeepExclude<U, I>>
: T extends {}
? { [K in keyof T]: DeepExclude<T[K], I> }
: Exclude<T, I>
I would love to have a DeepExclude. The above type doesn't seem to quite work yet.
type O = DeepExclude<{foo: number | {bar: number}}, {bar: number}>;
type O = {
foo: number | {
bar: number;
};
}
Interesting, I did not consider that use case. It works for us on simple cases like a class or an interface.
I already use a mapped exclude type in my project but haven't figured out how to make it fully recursive yet. I'd be curious if you come up with a recursive version that works for arrays and interfaces.
export type MappedExclude<T, E> = {
[P in keyof T]: Exclude<T[P], E>;
};
I asked on SO and this solution works well for me: https://stackoverflow.com/a/64900252/214950.
type DeepExclude<T, U> =
T extends U ? never :
T extends object ? {
[K in keyof T]: DeepExclude<T[K], U>
} : T;
This only works for simple objects and it wont work for arrays, sets, promises, etc.
It does work for arrays, actually.