ts-essentials icon indicating copy to clipboard operation
ts-essentials copied to clipboard

DeepExclude

Open Sytten opened this issue 5 years ago • 8 comments

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>

Sytten avatar Nov 11 '20 17:11 Sytten

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;
    };
}

domoritz avatar Nov 18 '20 18:11 domoritz

Interesting, I did not consider that use case. It works for us on simple cases like a class or an interface.

Sytten avatar Nov 18 '20 20:11 Sytten

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>;
};

domoritz avatar Nov 18 '20 21:11 domoritz

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;

domoritz avatar Nov 19 '20 20:11 domoritz

This only works for simple objects and it wont work for arrays, sets, promises, etc.

Sytten avatar Nov 19 '20 20:11 Sytten

It does work for arrays, actually.

Screen Shot 2020-11-19 at 12 53 38

domoritz avatar Nov 19 '20 20:11 domoritz