29785-medium-deep-omit

Back

  type DeepOmit<T, PropStr extends string> = 
  PropStr extends `${infer Prop}.${infer Rest}` 
    ? {
        [P in keyof T]: P extends Prop ? DeepOmit<T[P], Rest> : T[P]
      }
    : {
        [P in keyof T as P extends PropStr ? never : P]: T[P]
      } 

Solution by sunupupup #33490

  type DeepOmit<T extends any,K extends string> = K extends `${infer k}.${infer o}` 
  ? {[KK in keyof T]:KK extends k ? DeepOmit<T[KK],o>:T[KK]}
  :{[KK in keyof T as KK extends K ? never:KK ]:T[KK]}

Solution by fffqwhy #33026

type DeepOmit<O, Prop extends string> =
  Prop extends keyof O
  ? {[K in Exclude<keyof O, Prop>]: O[K]}
  : Prop extends `${infer Key extends keyof O & string}.${infer Rest extends string}`
    ? {[K in keyof O]: K extends Key ? DeepOmit<O[K], Rest> : O[K]}
    : O

Playground

Solution by teamchong #32995

type DeepOmit<T, Path extends string> = Path extends `${string}.${infer R}` 
  ? {
    [P in keyof T]: DeepOmit<T[P], R>
  }
  : T extends object
    ? Omit<T, Path>
    : T

Solution by keyurparalkar #32876


type DeepOmit<T,Keys> = {
  [K in keyof T as 
    K extends Keys? 
      never:
      K
  ]:K extends Keys?
      never:
      Keys extends `${infer F}.${infer R}`?
        K extends F?
          DeepOmit<T[K],R>:T[K]
        :T[K]
}
type obj = {
  person: {
    name: string;
    age: {
      value: number
    }
  }
}

type test1 = DeepOmit<obj, 'person'>    // {} 
Execute :[K in keyof T as
    K extends Keys? 
      never:
      K
  ]
type test2 = DeepOmit<obj, 'person.name'> // { person: { age: { value: number } } }
Execute:
[K in keyof T as 
    K extends Keys? 
      never:
      K
  ]:K extends Keys?
      never:
type test3 = DeepOmit<obj, 'name'> // { person: { name: string; age: { value: number } } }
Nothing to omit as obj does not have name parent key
type test4 = DeepOmit<obj, 'person.age.value'> // { person: { name: string; age: {} } }
Execute: recursive function  for child keys :
DeepOmit<T[K],R>:T[K]

Solution by wubrafiq807 #32624

type Copy<T> = {
  [P in keyof T]: T[P]
}

type DeepOmit<
  T extends Record<PropertyKey, any>,
  S extends string
> = S extends `${infer P}.${infer Rest}`
  ? Copy<Omit<T, P> & Record<P, DeepOmit<T[P], Rest>>>
  : Omit<T, S>;

Solution by Vampirelee #32594

// your answers
  type GetMember<T extends string, First extends string> = T extends `${First}.${infer Rest}` ? Rest : never;

  type DeepOmit<T extends object, K extends string> = {
    [key in keyof T as key extends K ? never : key]: T[key] extends object
      ? key extends string
        ? T[key] extends Date // Date는 객체긴 하지만 DeepOmit 재귀를 탈 필요는 없으므로 예외 처리
          ? T[key]
          : DeepOmit<T[key], GetMember<K, key>>
        : never
      : T[key];
  };

Solution by kakasoo #32437

type DeepOmit<T, S> = {
  [K in keyof T as K extends S ? never : K]: S extends `${K & string}.${infer R}`
    ? DeepOmit<T[K], R>
    : T[K];
};

Solution by vangie #32201

type Merge<T, U, R = Omit<T, keyof U> & U> = {[K in keyof R]: R[K]};

type DeepOmit<T extends Record<string, any>, U extends string> =
  U extends `${infer K}.${infer S}`
    ? K extends keyof T
      ? Merge<T, {[P in K]: DeepOmit<T[P], S>}>
      : T
    : Omit<T, U>

Solution by milletlovemouse #31065

type Shift<T extends any[]> = T extends [infer _F,...infer R] ? R : never;

type GetArray<T extends string, U extends any[] = []> = T extends `${infer F}.${infer R}` ? GetArray<R, [...U, F]> : [...U, T]

type DeepOmit<T extends object, U extends string, K extends any[] = GetArray<U>> = {
  [P in keyof T as P extends K[0] ? K['length'] extends 1 ? never : P : P]
  : 
  P extends K[0] ? T[P] extends object ? DeepOmit<T[P], U, Shift<K>> : T[P] : T[P]
}

Solution by moonpoet #31053

type DeepOmit<O, P extends string> = P extends `${infer K}.${infer Rest}` ? {
  [key in keyof O]: key extends K ? DeepOmit<O[key], Rest> : O[key]
} : Omit<O, P>

Solution by moonshadow-miao #30825

type O<T> = { [K in keyof T]: T[K] }
type DeepOmit<T, Keys extends string> = O<
  Keys extends `${ infer K extends keyof T & string }.${ infer Rest }`
    ? Omit<T, K> & Record<K, DeepOmit<T[K], Rest>>
    : Omit<T, Keys>
>

Solution by lvjiaxuan #30400

// your answers
type DeepOmit<T extends Record<string, any>, U extends string > = {
  [K in keyof T as K extends U ? never : K ]: U extends `${string}.${infer P}` ? DeepOmit<T[K], P> : T[K]
}

Solution by kerolossamir165 #30276

// your answers
type DeepOmit<T, K extends string> = T extends object
  ? {
      [P in keyof T]: P extends K
        ? never
        : K extends `${infer A}.${infer R}`
        ? A extends P
          ? P extends keyof T
            ? DeepOmit<T[P], R>
            : T[P]
          : T[P]
        : T[P];
    }
  : T;

Solution by janice143 #30219

type SplitKeys<KeysString extends string> = KeysString extends `${infer First}.${infer Rest}` ? [First,...SplitKeys<Rest>] : [KeysString];

type PlusOne<N extends number,Acc extends number[]=[]> = Acc['length'] extends N ? [...Acc,0]['length'] : PlusOne<N,[...Acc,0]>;  

type DeepOmit<Obj extends {[key:string]:any},KeysString extends string,KeysTuple extends string[] = SplitKeys<KeysString>,Index extends number = 0> = {
    [Key in keyof Obj as PlusOne<Index> extends KeysTuple['length'] ? Key extends KeysTuple[Index] ? never : Key : Key]: Obj[Key] extends Object ? PlusOne<Index> extends KeysTuple['length'] ? Obj[Key] : DeepOmit<Obj[Key],KeysString,KeysTuple,PlusOne<Index>>: Obj[Key];
}

Solution by idebbarh #30218

// 你的答案
type DeepOmit<T extends Record<string, any>, N extends string> = {
  [P in keyof T as P extends N ? never : P]: N extends `${any}.${infer R}` ? DeepOmit<T[P], R> : T[P]
}

Solution by YE840926098 #30153

// 你的答案
type DeepOmit<T extends Record<string, any>, N extends string> = {
  [P in keyof T as P extends N ? never : P]: N extends `${any}.${infer R}` ? DeepOmit<T[P], R> : T[P]
}

Solution by YE840926098 #30152

// 增加了对 key 的限制
type DeepKeyof<T> = T extends Record<string, any> ? {
  [K in keyof T]: K extends string ? K | `${K}.${DeepKeyof<T[K]>}` : never
}[keyof T] : never

type Clone<T> = T extends any ? { [K in keyof T]: T[K] } : never

type DeepOmit<T, Key extends DeepKeyof<T>> = Clone<
  Key extends `${infer K}.${infer Rest}`
    ? Omit<T, K> & {
      [Key in K]: K extends keyof T ? Rest extends DeepKeyof<T[K]> ? DeepOmit<T[K], Rest> : never : never
    }
    : Omit<T, Key>
>

Solution by XkSuperCool #30118

type DeepOmit<T, U extends string> = { [P in keyof T as P extends U ? never : P]:
  U extends `${infer K}.${infer R}` ?       //a.b.c
  P extends K ?                             //a extends a
  K extends keyof T ? DeepOmit<T[K], R> :   //DeepOmit<T[a], b.c>
  T[P] : T[P] : T[P] };

Solution by E-uler #29921

type DeepOmit<T, P extends string> =
  P extends `${infer K}.${infer Rest}`
    ? K extends keyof T
      ? {
        [Key in keyof T]: Key extends K ? DeepOmit<T[Key], Rest> : T[Key]
      }
      : T
    : Omit<T, P>

Solution by Sun79 #29871

type Split<T, D extends string> = T extends `${infer S }${D}${infer R}` ? [S, R] : [T];

type DeepOmit<T, U, Path = Split<U, ".">[0], R=Split<U, ".">[1] > = 
          Path  extends keyof T ? 
            R extends undefined ? 
                {[K in keyof T as K extends Path ? never: K]: T[K]} 
              : 
                {[K in keyof T]: K extends Path ? DeepOmit<T[Path], R>: T[K]} 
              :
          T

Solution by Ibarra11 #29868

type DeepOmit<T,Keys> = {
  [K in keyof T as 
    K extends Keys? 
      never:
      K
  ]:K extends Keys?
      never:
      Keys extends `${infer F}.${infer R}`?
        K extends F?
          DeepOmit<T[K],R>:T[K]
        :T[K]
}

Solution by jiangshanmeta #29866