15260-hard-tree-path-array

Back

type Path<T, U extends any[] = [], K extends keyof T = keyof T> = K extends any
  ? T[K] extends object
    ? [...U, K] | Path<T[K], [...U, K]>
    : [...U, K]
  : [T];

Solution by Vampirelee #32706

type Path<
  T extends object,
  P extends PropertyKey[] = [],
  K extends keyof T = keyof T
> = K extends unknown
  ? [...P, K] | (T[K] extends object ? Path<T[K], [...P, K]> : never)
  : never; 

Solution by vangie #32312

type Path<T extends object, P extends any[] = [], K extends keyof T = keyof T> = 
  K extends K 
    ? (T[K] extends object ? [...P, K] | Path<T[K], [...P, K]> : [...P, K]) 
  : never;

Solution by tarotlwei #31863

// your answers
type ToString<A, B> = A extends string ? B extends string ? `${A}_${B}` : never : never

type StringToArray<S> = S extends `${infer Key}_${infer Rest}` ? [Key, ...StringToArray<Rest>] : [S]

type Path<T> = StringToArray<keyof {
  [Key in keyof T as T[Key] extends object ? Key | ToString<Key, keyof T[Key]> : Key]: any
}> 

Solution by 437204933 #29733

type Path<T> = 
  T extends object
  ? { [B in keyof T]: [B] | [B, ...Path<T[B]>] }[keyof T]
  : []

Solution by RuyiLi #27890

type Path<T, K extends keyof T = keyof T> = K extends K
  ? [] | [K] | [K, ...(T[K] extends object ? Path<T[K]> : [])]
  : never;

Solution by JohnLi1999 #26304

type Path<T extends object, PrePaths extends (keyof any)[] = [], Key extends keyof T = keyof T> =
    Key extends Key ? [...PrePaths, Key] | (T[Key] extends object ? Path<T[Key] & object, [...PrePaths, Key]> : never) : never

Solution by zhuizhui0429 #26120

type Path<T> = T extends object
  ? {
      [K in keyof T]: [K] | [K, ...Path<T[K]>];
    }[keyof T]
  : [];

Solution by ozgurrgul #25844

type ValuesOf<T> = T[keyof T];
type PathHelper<T, _Link extends PropertyKey[] = []> = { [P in keyof T]: T[P] extends object ? ([P] | ValuesOf<PathHelper<T[P], [..._Link, P]>>) : [..._Link, P] };
type Path<T> = ValuesOf<PathHelper<T>>;

// old way
// type UnionToIntersection<T> = (T extends T ? (arg: T) => any : never) extends (arg: infer P) => any ? P : never;
// type UnionLast<T> = UnionToIntersection<(T extends T ? () => T : never)> extends () => infer R ? R : never;

// type Path<T extends object, K extends keyof T = keyof T, _UL = UnionLast<K>> = [K] extends [never] ? never :
//   [] | [_UL] | (_UL extends K ? T[_UL] extends object ? [_UL, ...Path<T[_UL]>] : never : never) | Path<T, Exclude<K, _UL>>;

Solution by E-uler #25362

type TreeObj = Record<string,unknown>

type PathInner<T extends TreeObj, K extends keyof T = keyof T> =
  K extends never ? never :
  [K] | [K, ...(T[K] extends TreeObj ? Path<T[K]>:[])]

type Path<T extends TreeObj> = [] | PathInner<T>

Solution by Derstilon #24360

// your answers
type Primitive = null | undefined | string | number | boolean | symbol | bigint

type Path<T, K extends any[] = []> =
  T extends Primitive
    ? K
    : K | Path<T[keyof T], [...K, keyof T]>

Solution by snakeUni #24292

type Path<T, K extends keyof T = keyof T> =
  K extends K
    ? [] | [K] | [K, ...(T[K] extends Record<string, unknown> ? Path<T[K]> : [])]
    : never

Solution by drylint #23146

type Path<T, Paths extends PropertyKey[] = []> = { [K in keyof T]: Path<T[K], [...Paths, K]> }[keyof T] | Paths

Playground

Solution by teamchong #22546

type Path<T, P extends PropertyKey[] = []> =
  P | { [K in keyof T]: Path<T[K], [...P, K]> }[keyof T]

Solution by Alexsey #22354

// your answers
type Wrap<T> = T extends T ? [T] : never
type Path<T extends Record<string, any>, Keys extends keyof T = keyof T> =
  Wrap<Keys> | (
    Keys extends any ?
      T[Keys] extends Record<string, any> ?
        [Keys,...Wrap<keyof T[Keys]>]
        : never
    : never
  )

Solution by YqxLzx #22286

type Path<T, _PrePaths extends string[] = []> = 
  T extends Record<string, any>
  ? {
      [P in keyof T]: _PrePaths | Path<T[P], [..._PrePaths, P & string]>
    }[keyof T]
  : _PrePaths

playground

As the challenge states, it is a mini version of Object Key Paths.

Solution by zhaoyao91 #22096

// your answers
type Path<T, R extends any[] = [], K = keyof T>
    = K extends keyof T
    ? T[K] extends { [P in any]: any }
    ? [...R, K] | Path<T[K], [...R, K]>
    : [...R, K]
    : R

Solution by goddnsgit #22027

type Path<
  T extends Record<string, any>,
  G extends keyof T = keyof T
> = G extends G
  ? T[G] extends Record<string, any>
    ? [`${G & string}`, ...Path<T[G]>] | [`${G & string}`]
    : [`${G & string}`]
  : never;

Solution by so11y #21349

type Path<T> = T extends object
  ? {
      [K in keyof T]: [K] | [K, ...Path<T[K]>];
    }[keyof T]
  : never;

Solution by bigcreate #20927

// your answers
type Path<T, P extends any[] = []> = Exclude<
  {
    [K in keyof T]: T[K] extends any[]
      ? P | Path<T[K], [...P, K]>
      : T[K] extends object
      ? P | Path<T[K], [...P, K]>
      : P | [...P, K];
  }[keyof T],
  []
>;

Solution by venusliang #20903

type Path<T, Prefix extends (keyof any)[] = [], U extends keyof T = keyof T, > =
  U extends U
    ? [...Prefix, U] | (T[U] extends object ? Path<T[U], [...Prefix, U]> : never)
    : never;

Solution by xiexuan-star #20140

type Path<T, K extends keyof T = keyof T> = K extends unknown
  ? T[K] extends Record<any, unknown>
    ? [K] | [K, ...Path<T[K]>]
    : [K]
  : never

Solution by theoolee #19810

// your answers
type Path<T extends Record<PropertyKey, unknown>, Result extends any[] = [], K extends keyof T = keyof T> =  K extends keyof T
                                                                                            ? [...Result, K] | (T[K] extends Record<PropertyKey, unknown> 
                                                                                                                        ? Path<T[K], [...Result, K]> 
                                                                                                                        : never)
                                                                                            : never;

Solution by jiaaoMario #18817

type Path<T> = T extends Record<PropertyKey, unknown>
  ? {
      [P in keyof T]: [P, ...Path<T[P]>] | [P];
    }[keyof T]
  : never;

Solution by baian1 #18292

type Path<T,S extends any[] = [],K extends keyof T = keyof T> = 
  K extends keyof T?
    [...S,K] | (T[K] extends Record<keyof any,any>? Path<T[K],[...S,K]>:never)
    :never 

Solution by jiangshanmeta #18261

type Wrap<T> = T extends T ? [T] : never
type Path<T extends Record<string, any>, Keys extends keyof T = keyof T> =
  Wrap<Keys> | (
    Keys extends any ?
      T[Keys] extends Record<string, any> ?
        [Keys,...Wrap<keyof T[Keys]>]
        : never
    : never
  )

Solution by XkSuperCool #18171