DEV Community

Acid Coder
Acid Coder

Posted on

Typescript Loop Tuple With Length > 1000

We cannot recurse tuple with more than 1000 length due to TS limitation

In this example we try to feed a recursion utility RebuildTuple with 9990 length tuple

type CreateArrayWithLengthX<
    LENGTH extends number,
    ACC extends unknown[] = [],
> = ACC['length'] extends LENGTH
    ? ACC
    : CreateArrayWithLengthX<LENGTH, [...ACC, 1]>

type Exceed999<
    ARR extends 1[],
> = [...ARR['length'] extends 0 ? [] : [...CreateArrayWithLengthX<999>, ...Exceed999<ARR extends [...infer S extends 1[], infer P] ? S : never>]]

// create 9990 length array
type Tuple9990 = Exceed999<CreateArrayWithLengthX<10>>

type RebuildTuple<T extends unknown, ACC extends unknown[] = []> = T extends [infer S, ...infer R] ? RebuildTuple<R, [...ACC, S]> : ACC

type C = RebuildTuple<Tuple9990>
Enter fullscreen mode Exit fullscreen mode

TS will complains

Image description

playground

reference:create tuple with more than 1000 length

However we can use the mapped type to loop the tuple:

type RebuildTuple<T extends unknown> ={ [K in keyof T] : T[K] }
Enter fullscreen mode Exit fullscreen mode

playground
no error
Image description

let us do further comparison by using it in function generic:

type RebuildTuple<T extends unknown, ACC extends unknown[]= [] >= T extends [infer S, ...infer R] ? RebuildTuple<R,[...ACC,S]>: ACC
type RebuildTuple1<T extends unknown[]> = { [K in keyof T]: T[K] }


type A = RebuildTuple<[1,2,3]>
//   ^?
type A1 = RebuildTuple1<[1,2,3]>
//   ^?

const abc=<T extends unknown[]>(v:T extends never ? T : RebuildTuple<T>)=>{}
const abc1=<T extends unknown[]>(v:T extends never ? T : RebuildTuple1<T>)=>{}

abc([1,2,3])
//^?
abc1([1,2,3])
//^?
Enter fullscreen mode Exit fullscreen mode

playground

Image description

It can't infer the type, what is wrong?

This is because we forgot to narrow the type in RebuildTuple1 down to a tuple

type RebuildTuple<T extends unknown, ACC extends unknown[]= [] >= T extends [infer S, ...infer R] ? RebuildTuple<R,[...ACC,S]>: ACC
type RebuildTuple1<T extends unknown[]> = T extends [ infer S,...infer R] ? { [K in keyof [S,...R]] : [S,...R][K] } : never


type A = RebuildTuple<[1,2,3]>
//   ^?
type A1 = RebuildTuple1<[1,2,3]>
//   ^?

const abc=<T extends unknown[]>(v:T extends never ? T : RebuildTuple<T>)=>{}
const abc1=<T extends unknown[]>(v:T extends never ? T : RebuildTuple1<T>)=>{}

abc([1,2,3])
//^?
abc1([1,2,3])
//^?
Enter fullscreen mode Exit fullscreen mode

playground

the hint doesn't look pretty
Image description

but they are indeed the same thing

Image description

Top comments (0)