[Typescript] 112. Hard - DeepPick

Implement a type DeepPick, that extends Utility types Pick. A type takes two arguments.

For example:


type obj = {
  name: 'hoge', 
  age: 20,
  friend: {
    name: 'fuga',
    age: 30,
    family: {
      name: 'baz',  
      age: 1 
    }
  }
}

type T1 = DeepPick<obj, 'name'>   // { name : 'hoge' }
type T2 = DeepPick<obj, 'name' | 'friend.name'>  // { name : 'hoge' } & { friend: { name: 'fuga' }}
type T3 = DeepPick<obj, 'name' | 'friend.name' |  'friend.family.name'>  // { name : 'hoge' } &  { friend: { name: 'fuga' }} & { friend: { family: { name: 'baz' }}}

 

/* _____________ Your Code Here _____________ */
type UnionToInteresction<U> = (U extends any ? (x: U) => void : never) extends ((x: infer I) => void) ? I : never;
type Prop<T, U> = U extends keyof T
  ? {[Key in U]: T[Key]}
  : U extends `${infer P}.${infer RT}`
    ? P extends keyof T
      ? {[Key in P]: Prop<T[Key], RT>}
      : never
    :never;
type DeepPick<T, U> = UnionToInteresction<Prop<T, U>>


/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type Obj = {
  a: number
  b: string
  c: boolean
  obj: {
    d: number
    e: string
    f: boolean
    obj2: {
      g: number
      h: string
      i: boolean
    }
  }
  obj3: {
    j: number
    k: string
    l: boolean
  }
}

type cases = [
  Expect<Equal<DeepPick<Obj, ''>, unknown>>,
  Expect<Equal<DeepPick<Obj, 'a'>, { a: number }>>,
  Expect<Equal<DeepPick<Obj, 'a' | ''>, { a: number } & unknown>>,
  Expect<Equal<DeepPick<Obj, 'a' | 'obj.e'>, { a: number } & { obj: { e: string } }>>,
  Expect<Equal<DeepPick<Obj, 'a' | 'obj.e' | 'obj.obj2.i'>, { a: number } & { obj: { e: string } } & { obj: { obj2: { i: boolean } } }>>,
]

 

posted @ 2022-11-21 15:32  Zhentiw  阅读(19)  评论(0编辑  收藏  举报