32427-hard-unbox

Back

type Pop<T extends any[]> = T extends [...infer _, infer Last] ? Last : [];
type RangeGen<T, R extends any[] = []> = R["length"] extends T
  ? R
  : RangeGen<T, [...R, unknown]>;
type SubOne<T> =
  RangeGen<T> extends [...infer First, infer _] ? First["length"] : 0;

type UnboxArray<T> = T extends (infer F)[] ? F : T;
type UnboxFunc<T> = T extends (...args: any) => infer R ? R : T;
type UnboxPromise<T> = T extends PromiseLike<infer R> ? R : T;

type Unwrap<T> = UnboxFunc<UnboxArray<UnboxPromise<T>>>;

type Unbox<T, L extends number = 0, R extends any[] = [T]> = [T] extends [
  Unwrap<T>,
]
  ? Pop<R>
  : L extends 0
    ? Unbox<Unwrap<T>, L, [...R, Unwrap<T>]>
    : SubOne<L> extends 0
      ? Unwrap<T>
      : Unbox<Unwrap<T>, SubOne<L>, [...R, Unwrap<T>]>;

Solution by ickynavigator #33903

type Unbox<T, Depth extends number = 0, C extends string = '0'>
  = (Depth extends 0 ? '' : `${Depth}`) extends C ? T
  : T extends Box<infer I> ? Unbox<I, Depth, PlusOne<C>>
  : T

type Box<I> = (() => I) | I[] | PromiseLike<I>

type PlusOne<S>
  = S extends `${infer L}9` ? L extends '' ? '10' : `${PlusOne<L>}0`
  : S extends `${infer L}8` ? `${L}9` : S extends `${infer L}7` ? `${L}8` : S extends `${infer L}6` ? `${L}7` : S extends `${infer L}5` ? `${L}6` : S extends `${infer L}4` ? `${L}5` : S extends `${infer L}3` ? `${L}4` : S extends `${infer L}2` ? `${L}3` : S extends `${infer L}1` ? `${L}2` : S extends `${infer L}0` ? `${L}1` : '1'

Playground

Solution by teamchong #32987

type UnboxRec<T, D, C extends 1[]> = C['length'] extends D
  ? T
  : T extends (readonly (infer I)[] | PromiseLike<infer I> | (() => infer I))
    ? UnboxRec<I, D, [...C, 1]>
    : T;

type Unbox<T, D = 0> = UnboxRec<T, Exclude<D, 0>, []>;

Solution by alexandroppolus #32965

type Unbox<T, L extends number = 0, C extends number[] = []> =
  C['length'] extends L
    ? L extends 0
      ? Unbox<T, L, [0]>
      : T
    : T extends ((...args: any[]) => infer R) | (infer R)[] | Promise<infer R>
      ? Unbox<R, L, [...C, 0]>
      : T

Solution by XkSuperCool #32808

type SimpleUnbox<T> =
    T extends (infer V)[] ? V :
    T extends () => infer V ? V :
    T extends Promise<infer V> ? V :
    T;

type DeepUnbox<T, R = SimpleUnbox<T>> = T extends R ? T : DeepUnbox<R>;

type FakeArray<N extends number, T extends any[] = []> = T['length'] extends N ? T : FakeArray<N, [...T, any]>;

type Decrement<N extends number, A = FakeArray<N>> = A extends [any, ...infer T extends any[]] ? T['length'] : -1;

type Unbox<T, C extends number = -1> =
  C extends -1 | 0 ? DeepUnbox<T> :
    C extends 1 ? SimpleUnbox<T> :
     Unbox<SimpleUnbox<T>, Decrement<C>>;

Solution by alexbidenko #32566

type Primitive = number | string | boolean

type Unbox<T, N extends number = 0, Cur extends 1[] = [1] >
    = Cur['length'] extends N
      ? T extends () => infer R1 ? R1
        : T extends (infer R2)[] ? R2
          : T extends Promise<infer R3> ? R3
            : T
      : T extends () => infer R1 ? R1 extends Primitive ? R1 : Unbox<R1, N, [...Cur, 1]>
        : T extends (infer R2)[] ? R2 extends Primitive ? R2 : Unbox<R2, N, [...Cur, 1]>
          : T extends Promise<infer R3> ? R3 extends Primitive ? R3 : Unbox<R3, N, [...Cur, 1]>
            : T

Solution by Heonys #32511

type Unbox<T, Depth = 0, Count extends any[] = [1]> = T extends ((...args: any[]) => infer R) | (infer R)[] | Promise<infer R>
  ? Count['length'] extends Depth ? R : Unbox<R, Depth, [...Count, 1]>
  : T

Solution by Sun79 #32469

type Unbox<T, Deep extends number = 0, _DeepRecorder extends 1[] = []> =
  Deep extends 0 ? Unbox<T, -1> : //To Infinity
  _DeepRecorder[`length`] extends Deep ? T :
  T extends Promise<infer R> ? Unbox<R, Deep, [..._DeepRecorder, 1]> :
  T extends () => infer R ? Unbox<R, Deep, [..._DeepRecorder, 1]> :
  T extends (infer R)[] ? Unbox<R, Deep, [..._DeepRecorder, 1]> :
  T;

Solution by E-uler #32458