03243-medium-flattendepth

Back

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

// your answers
type Flatten<T> = T extends any[] ? T extends [infer S, ...infer R] ? [...(S extends any[] ? S : [S]), ...Flatten<R>]: T : never;
type FlattenDepth<A extends unknown[], D extends number = 1, C  extends unknown[] = []> = C['length'] extends D ? A : FlattenDepth<Flatten<A>, D, ['', ...C]>;

Solution by Hencky #26689

type NumberLiteral = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
type MinusOneMap = {
  '0': 9
  '1': 0
  '2': 1
  '3': 2
  '4': 3
  '5': 4
  '6': 5
  '7': 6
  '8': 7
  '9': 8
}
type PlusOneMap = {
  '0': 1
  '1': 2
  '2': 3
  '3': 4
  '4': 5
  '5': 6
  '6': 7
  '7': 8
  '8': 9
  '9': 0
}

type NumberToString<T extends number> = `${T}`

type RemoveStartWithZeros<S extends string> = S extends '0'
  ? S
  : S extends `${0}${infer Rest}`
    ? `${RemoveStartWithZeros<Rest>}`
    : S

type ReverseString<S extends string> = S extends `${infer First}${infer Rest}`
  ? `${ReverseString<Rest>}${First}`
  : ''

// type RemoveUnit<S extends string> = S extends `${infer F}${infer R}`
//   ? F extends `${number}`
//     ? `${F}${RemoveUnit<R>}`
//     : `${RemoveUnit<R>}`
//   : S

type Initial<S extends string> = ReverseString<S> extends `${infer _}${infer Rest}`
  ? `${ReverseString<Rest>}`
  : S

type MinusOneForString<S extends string, T extends string = Initial<S>> = S extends `${T}${infer Last extends NumberLiteral}`
  ? Last extends '0'
    ? `${MinusOneForString<T>}${MinusOneMap[Last]}`
    : `${T}${MinusOneMap[Last]}`
  : never

type PlusOneForString<S extends string, T extends string = Initial<S>> = S extends `${T}${infer Last extends NumberLiteral}`
  ? Last extends '9'
    ? T extends '9'
      ? `${1}${PlusOneForString<T>}${PlusOneMap[Last]}`
      : `${PlusOneForString<T>}${PlusOneMap[Last]}`
    : `${T}${PlusOneMap[Last]}`
  : S

type GetSignSymbol<T extends string> = T extends `${infer _F extends '-'}${infer _L extends number}`
  ? '-'
  : '+'

type ParseInt<T extends string> =
  RemoveStartWithZeros<T> extends `${infer Digit extends number}`
    ? Digit
    : never

type PlusOne<T extends number, S = GetSignSymbol<`${T}`>> = T extends -1
  ? 0
  : S extends '+'
    ? ParseInt<PlusOneForString<NumberToString<T>>>
    : ParseInt<MinusOneForString<NumberToString<T>>>

// type PlusOne<T extends number> = ParseInt<PlusOneForString<`${T}`>>

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

// Main
type FlattenDepth<T extends any[], D extends number = 1, C extends number = 0> =
    D extends C
      ? T
      : T extends [infer F, ...infer R]
        ? F extends [...infer L]
          ? [...FlattenDepth<L, D, PlusOne<C>>, ...FlattenDepth<R, D, C>]
          : [F, ...FlattenDepth<R, D, C>]
        : T

Solution by HaoxueAllen #26547

正常递归之外,增加深度,正常情况下不能递减,刚好之前有个training是MinusOne 用他来加入计算即可

// your answers
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

Solution by adoin #26213

// your answers
type Flatten<A extends unknown[]> = 
  A extends [infer X, ...infer Y] ? 
    X extends unknown[] ? [...X, ...Flatten<Y>] : [X, ...Flatten<Y>] :
    [];

type FlattenDepth<Target extends unknown[], Depth extends number = 1, Arr extends unknown[] = []> = 
  Arr['length'] extends Depth ? 
    Target :
    Flatten<Target> extends Target ?
      Target :
      FlattenDepth<Flatten<Target>, Depth, [unknown, ...Arr]>

The key point is Flatten<Target> extends Target. Without it, when our target depth number is very large, we will receive an error prompt. But with this judgement, we can stop our iteration earlier.

Solution by kiki-zjq #25160

type Flatten<T extends unknown[]> = T extends [infer K, ...infer U]
  ? K extends unknown[]
    ? [...K, ...Flatten<U>]
    : [K, ...Flatten<U>]
  : [];

type FlattenDepth<T extends unknown[], D extends number = 1, A extends 0[] = []> = A['length'] extends D
  ? T
  : Flatten<T> extends T 
    ? T
    : FlattenDepth<Flatten<T>, D, [...A, 0]>

Solution by yungo1846 #24833