03243-medium-flattendepth

Back

type FlattenDepth<T extends any[], S extends number = 1, U extends any[] = []> = U['length'] extends S
  ? T
  : T extends [infer F, ...infer R]
    ? F extends any[]
      ? [...FlattenDepth<F, S, [...U, 1]>, ...FlattenDepth<R, S, U>]
      : [F, ...FlattenDepth<R, S, U>]
    : T;

Solution by wendao-liu #35059

type FlattenDepth<T, Number = 1, S extends number[] = []> = Number extends S['length'] ? T
  : T extends [infer Pre, ...infer Next]
    ? Pre extends any[]
      ? [...FlattenDepth<Pre, Number, [...S, 1]>, ...FlattenDepth<Next, Number, S>]
      : [Pre, ...FlattenDepth<Next, Number, S>]
    : []

Solution by devshinthant #34960

先实现普通Flatten,由于普通Flatten本身会递归到完全展平为止,再添加一个递归深度条件让它拥有提前终止递归的能力即可。

type FlattenDepth<T, U extends number = 1> = U extends 0
  ? T
  : T extends [infer First, ...infer Rest]
    ? First extends unknown[]
      ? [...FlattenDepth<First, MinusOne<U>>, ...FlattenDepth<Rest, U>]
      : [First, ...FlattenDepth<Rest, U>]
    : T

使用 2257 - MinusOne<T>

type Map = [9, 0, 1, 2, 3, 4, 5, 6, 7, 8]
type ReverseString<T extends string> = T extends `${infer First}${infer Rest}` ? `${ReverseString<Rest>}${First}` : T
type Decrease<T extends string> = T extends `${infer First extends number}${infer Rest}` ? `${Map[First]}${First extends 0 ? Decrease<Rest> : Rest}` : T
type ParseInt<T extends string> = T extends `${0}${infer Rest}` ? ParseInt<`${Rest}`> : (T extends `${infer N extends number}` ? N : 0)
type MinusOne<T extends number> = T extends 0 ? -1 : ParseInt<ReverseString<Decrease<ReverseString<`${T}`>>>>

Solution by 2083335157 #34897

// your answers
// 难点在于 deep层数
type FlattenDepth<T extends any[], D extends number = 1, U extends any[] = []> =
  T extends [infer F, ...infer Rest] ?
      F extends any[] ? 
          U['length'] extends D ? 
            [F, ...FlattenDepth<[...Rest], D, U>] :
            [...FlattenDepth<F, D, [...U, 1]>, ...FlattenDepth<Rest, D, U>] 
      : [F, ...FlattenDepth<[...Rest], D, U>]
  : T

Solution by Jayce-liang #34776

type FlattenOnce<T extends Array<any>> = T extends [infer F, ...infer Rest] 
                                                  ? F extends Array<any>
                                                    ? [...F, ...FlattenOnce<Rest>] 
                                                    : [F, ...FlattenOnce<Rest>]
                                                  : []


type FlattenDepth<T extends Array<any>, Depth = 1, DepthCount extends any[] = []> = 
  DepthCount["length"] extends Depth
  ? T
  : FlattenDepth<FlattenOnce<T>, Depth, [...DepthCount, 'increment']>

Solution by maximallain #34775

type FlattenDepth<T extends any[], L extends number = 1, U extends any[] = []> = U['length'] extends L ? T : 
T extends [infer V, ...infer rest] ? 
V extends any[] ? [...FlattenDepth<V, L, [...U, 1]>, ...FlattenDepth<rest, L, U>] : [V, ...FlattenDepth<rest, L, U>]
 : T

Solution by ouzexi #34063

// 你的答案
type FlattenDepth<T extends any[], N extends number = 1, L extends any[] = []> = T extends [infer H, ...infer R] ? H extends any[] ? L['length'] extends N ? [H, ...FlattenDepth<R, N, L>] : [...FlattenDepth<H, N, [true, ...L]>, ...FlattenDepth<R, N, L>]: [H, ...FlattenDepth<R, N, L>] : T;

Solution by HelloGGG #33557

type FlattenDepth<T extends any[], U extends number = 1, Q extends any[] = []> = T extends [
  infer R,
  ...infer P,
]
  ? R extends any[]
    ? Q['length'] extends U
      ? [R, ...FlattenDepth<P, U>]
      : [...FlattenDepth<[...R], U, [...Q, 1]>, ...FlattenDepth<P, U>]
    : [R, ...FlattenDepth<P, U, [...Q]>]
  : T;

Solution by Shaocang #31636

// your answers
type FlattenOne<T extends any[]> = T extends [infer F, ...infer R]
  ? F extends any[]
    ? [...F, ...FlattenOne<R>]
    : [F, ...FlattenOne<R>]
  : T;

type CheckFlat<T extends any[]> = T extends [infer F, ...infer R]
  ? F extends any[]
    ? false
    : CheckFlat<R>
  : true;

type FlattenDepth<
  T extends any[],
  N extends number = 1,
  Rec extends any[] = []
> = CheckFlat<T> extends true
  ? T
  : Rec["length"] extends N
  ? T
  : FlattenDepth<FlattenOne<T>, N, [0, ...Rec]>;

Solution by chenqy-yh #31207

type FlattenDepth<T, D extends number = 1, U extends unknown[] = MakeNumberToArray<D>> = 0 extends U['length']
  ? T
  : T extends [infer F, ...infer R]
  ? F extends unknown[]
    ? U extends [unknown, ...infer UR]
      ? [...FlattenDepth<F, D, UR>, ...FlattenDepth<R, D, U>]
      : never
    : [F, ...FlattenDepth<R, D, U>]
  : T;

Solution by leejaehyup #30828

// your answers
type FlattenDepthOne<T extends any[]> =
  T extends [infer F, ...infer Rest]
    ? F extends any[]
      ? [...F, ...FlattenDepthOne<Rest>]
      : [F, ...FlattenDepthOne<Rest>]
    : []

type CanFlatten<T> = T extends [infer F, ...infer Rest]
  ? F extends any[]
    ? true
    : CanFlatten<Rest>
  : false

type FlattenDepth<T extends any[], D=1, C extends number[] = []> =
  C['length'] extends D
    ? T
    : CanFlatten<T> extends true
      ? FlattenDepth<FlattenDepthOne<T>, D, [...C, 1]>
      : T
    
    

Solution by enochjs #30481

type FlattenDepth<T extends unknown[], N extends number = 1, C extends number[] = []> = T extends [...infer A, infer B] 
  ?
     B extends Array<unknown>
      ? 
        C['length'] extends N
          ?
            [...FlattenDepth<A, N, []>, B]
          : FlattenDepth<[...A, ...B], N, [...C, 0]>
      : [...FlattenDepth<A, N, []>, B]
  : T

Solution by zhangqiangzgz #30176

The following solution makes use of MinusOne:

type FlattenDepth<T extends any[], D extends number = 1> =
    D extends 0 ? T :
        T extends [infer F, ...infer R]
            ? F extends any[]
               ? [...FlattenDepth<F, MinusOne<D>>, ...FlattenDepth<R, D>]
               : [F, ...FlattenDepth<R, D>]
            : T

You can find my version of MinusOne here: 2257 - MinusOne - Short solution with explanation.

But other solutions that use an auxiliary array for counting the depth (e.g. this one: 3243 - FlattenDepth #3364) are simpler and, as nesting depth requires only a very small number range, preferable.

Solution by sbr61 #30115

type FlattenOnce<T extends any[]> = 
T extends [infer F, ...infer R] ? 
[...F extends [...infer K] ? 
K : 
[F], ...FlattenOnce<R> ] : 
T;

type FlattenDepth<T, Times extends number=1, P extends any[] = []> = 
T extends any[] ? 
P extends {length: Times} ? 
T : 
T extends FlattenOnce<T> ? 
T : 
FlattenDepth<FlattenOnce<T>, Times, [...P, any] > : never;

Solution by DmitriiBr #29567

type FlattenDepth<
  T extends unknown[],
  D extends number = 1,
  S extends unknown[] = []
> = S["length"] extends D
  ? T
  : T extends [infer F, ...infer Rest]
  ? F extends unknown[]
    ? [...FlattenDepth<F, D, [...S, number]>, ...FlattenDepth<Rest, D, S>]
    : [F, ...FlattenDepth<Rest, D, S>]
  : T;

Solution by DoubleWoodLin #28703

type ParseInt<T extends string> = T extends ${infer Num extends number} ? Num : T;

type RemoveLeadingZero<T extends string> = T extends 0${infer Str} ? Str extends "" ? "0" : RemoveLeadingZero<Str> : T;

type ReverseStr<T extends string> = T extends ${infer F}${infer R}?${ReverseStr}${F} : T;

type InnerMinusOne<T extends string> = T extends ${infer F extends number}${infer R}? F extends 0 ?9${InnerMinusOne}:${[9, 0, 1, 2, 3, 4, 5, 6, 7, 8][F]}${R} : T;

type MinusOne<T extends number> = ParseInt< RemoveLeadingZero<ReverseStr<InnerMinusOne<ReverseStr<${T}`>>>>

;`

type FlattenDepth<T extends unknown[], D extends number = 1> = D extends 0 ? T : T extends [infer F, ...infer Rest] ? F extends unknown[] ? [...FlattenDepth<F, MinusOne<D>>, ...FlattenDepth<Rest, D>] : [F, ...FlattenDepth<Rest, D>] : T;

Solution by DoubleWoodLin #28702

// your answers
type FlattenDepth<
  T extends any[],
  S extends number = 1,
  U extends any[] = []
> = U['length'] extends S
  ? T
  : T extends [infer F, ...infer R]
  ? F extends any[]
    ? [...FlattenDepth<F, S, [...U, 1]>, ...FlattenDepth<R, S, U>]
    : [F, ...FlattenDepth<R, S, U>]
  : T

Solution by daiki-skm #28306

// your answers
type Check<T extends any[]> = T extends [infer F, ...infer Rest] ? F extends any[] ? true : Check<Rest> : false
type Flatten<T extends any[], R extends any[] = []> = T extends [infer F, ...infer Rest] ? F extends any[] ? Flatten<Rest, [...R, ...F]> : Flatten<Rest, [...R, F]> : R
type FlattenDepth<T extends any[], D extends number = 1, C extends any[] = []> =Check<T> extends true? D extends C['length'] ? T : FlattenDepth<Flatten<T>, D, [...C, any]>:T

Solution by AAA611 #27881

type FlattenOnce<T extends any[]> = T extends [infer F, ...infer R]
  ? F extends any[]
    ? [...F, ...FlattenOnce<R>]
    : [F, ...FlattenOnce<R>]
  : []

type IsFlatten<T extends any[]> = T extends [infer F, ...infer R]
  ? F extends any[]
    ? false
    : IsFlatten<R>
  : true

type FlattenDepth<T extends any[], U extends number = 1, S extends unknown[] = []> = 
  S['length'] extends U
    ? T
    : IsFlatten<T> extends true
      ? T
      : FlattenDepth<FlattenOnce<T>, U, [...S, unknown]>

Solution by jazelly #27857


type FlattenDepth<T, N extends number = 1, U extends any[] = []> = U['length'] extends N ?
  T :
  T extends [infer F, ...infer O] ?
  F extends any[] ? [...FlattenDepth<F, N, [...U, 0]>, ...FlattenDepth<O, N, U>] :
  [F, ...FlattenDepth<O, N, U>] : T

Solution by 8471919 #27831

type FlattenOnce<T extends any[], U extends any[] = []> T extends [infer L, ...infer R]
? L extends any[] ? FlattenOnce<R, [...U, ...L] : FlattenOnce<R, [...U, L]>
: U

type FlattenDepth<
  T extends any[],
  U extends number = 1,
  P extends any[] = []
> = P['length'] extends U ? T
: FlattenOnce<T> extends T ? T
: FlattenDepth<FlattenOnce<T>, U, [...P, any]>

Solution by isntkyu #27773

type FlattenDepth<
  A extends any[], 
  I extends number = 1, 
  _C extends number[] = []
> = I extends _C['length'] ? A : 
  A extends [infer First, ...infer Rest] ? 
    First extends any[] ? 
      [...FlattenDepth<First, I, [..._C, 0]>, ...FlattenDepth<Rest, I, _C>] :
      [First, ...FlattenDepth<Rest, I, _C>] 
    : A; 

Solution by jjswifty #27639

type FlattenDepth<
  A extends unknown[],
  Depth extends number = 1,
  CountArr extends unknown[] = [],
  Result extends unknown[] = []
> = CountArr["length"] extends Depth
  ? A
  : A extends [infer First, ...infer Rest]
  ? First extends [...infer contents]
    ? FlattenDepth<
        Rest,
        Depth,
        CountArr,
        [...Result, ...FlattenDepth<contents, Depth, [...CountArr, 0]>]
      >
    : FlattenDepth<Rest, Depth, CountArr, [...Result, First]>
  : Result;

Solution by alythobani #27542

type FlattenDepth<T, Number = 1, S extends number[] = []> = Number extends S['length'] ? T
  : T extends [infer Pre, ...infer Next]
    ? Pre extends any[]
      ? [...FlattenDepth<Pre, Number, [...S, 1]>, ...FlattenDepth<Next, Number, S>]
      : [Pre, ...FlattenDepth<Next, Number, S>]
    : []
/

Solution by jiechliu #27452

type FlattenDepth<T extends unknown [], U extends number = 1, Counter extends unknown[] = [] > = U extends 1 ? FlattenOne<T> : T extends [infer F, ...infer R] 
                                                                                            ? F extends unknown[] 
                                                                                              ? Counter['length'] extends U 
                                                                                                ?  [F, ...FlattenDepth<R, U, []>]
                                                                                                : [...FlattenDepth<F,U,[...Counter, 1]>, ...FlattenDepth<R,U,[]>]
                                                                                              : [F, ...FlattenDepth<R,U,[...Counter]>]
                                                                                            : []

Solution by nikitashevchenkodp #27104

type FlattenOnce<T> = T extends [infer F, ...(infer R)]
  ? [...(F extends any[] ? F : [F]), ...FlattenOnce<R>]
  : T;
type FlattenDepth<
  T,
  N extends number = 1,
  D extends any[] = []
> = T extends any[]
  ? D["length"] extends N
    ? T
    : FlattenOnce<T> extends T
    ? T
    : FlattenDepth<FlattenOnce<T>, N, [...D, ""]>
  : T;

Solution by smileboyi #26968

type FlattenDepth<
  T extends any[],
  C extends number = 1,
  U extends any[] = []
> = T extends [infer First,...infer Rest]
  ? First extends any[]                         // if First element is array
    ? U['length'] extends C                     // if flatten depth === C
      ? [First, ...FlattenDepth<Rest, C, U>]
      : [
          ...FlattenDepth<First, C, [0,...U]>,  // flatten First element for C-1 more times
          ...FlattenDepth<Rest, C, U>           // and FlattenDepth<Rest, C>
        ]
    : [First,...FlattenDepth<Rest, C, U>]
  : T;

Solution by se030 #26945

type Flatten<T extends any[]> = T extends [ infer F, ...infer Rest] ? (F extends any[] ?  [...F , ...Flatten<Rest> ] : [F, ...Flatten<Rest>]) : [];
type FlattenDepth<T extends any[], Depth = 1, A extends any[] = []> = A['length'] extends Depth ? T : FlattenDepth<Flatten<T>, Depth, [...A, '']>

Solution by jsujeong #26779

// your answers
type FlattenDepth<T, U extends number = 1, P extends any[] = [], A extends any[] = []> =
T extends any [] ?
  T extends [infer L, ...infer R] ? 
    A['length'] extends U ? T : FlattenDepth<R, U, [...P, ...FlattenDepth<L, U, [], [...A, U]>]>  
    : P 
  : [T]

Solution by CheolMinBae #26777

type FlattenDepth<T extends unknown[], N extends number = 1, Acc extends unknown[] = []>
= T extends [infer F, ...infer Rest]
  ? F extends unknown[]
    ? Acc['length'] extends N
      ? [F, ...FlattenDepth<Rest, N, Acc>]
      : [...FlattenDepth<F, N, [...Acc, never]>, ...FlattenDepth<Rest, N, Acc>]
    : [F, ...FlattenDepth<Rest, N, Acc>]
  : T

// error: Type instantiation is excessively deep and possibly infinite.
// type ToNumber<T extends unknown[]> = T['length']
// type ToArray<T extends number, Arr extends unknown[] = []> = ToNumber<Arr> extends T ? Arr : ToArray<T, [...Arr, undefined]>
// type Negative<T extends number> = `-${T}` extends `${infer V extends number}` ? V : never
// type Add<A extends number, B extends number> = ToNumber<[...ToArray<A>, ...ToArray<B>]>
// type Sub<A extends number, B extends number>
//   = ToArray<A> extends [...ToArray<B>, ...infer Rest] ? ToNumber<Rest>
//     : ToArray<B> extends [...ToArray<A>, ...infer Rest] ? Negative<ToNumber<Rest>>
//       : never
// type MinusOne<N extends number> = Sub<N, 1>

// type FlattenOnce<T extends unknown[]> = T extends [infer F, ...infer Rest]
//   ? F extends unknown[] ? [...F, ...FlattenOnce<Rest>] : [F, ...FlattenOnce<Rest>]
//   : T
// type FlattenDepth<T extends unknown[], N extends number = 1>
//   = N extends 0
//     ? T
//     : FlattenDepth<FlattenOnce<T>, MinusOne<N>>

Solution by tokyo9pm #26728