Typescript Loop Tuple With Length > 1000
Tags: webdev, javascript, typescript, programming
Published: 2022-12-24 23:23:33

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

```ts
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>
```
TS will complains

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d7ot8jvpczofl4vmcahd.png)

[playground](https://www.typescriptlang.org/play?#code/C4TwDgpgBAwgThAhsCBBOdEgOoEtgAWAMhAHYDmhAGgDwBQUjURAogHIDiAKgBJQQAPFKQAmAZyikArgFsARhDgAaBk1QwY-IWXFQppANakA9gHdSAbQC6UALxRrKgHx2o6mBYDkAGzKUCnjaCwrqsnLyqjAD8bhqRUABcsAjIaBhYeIQkFNQ0Ydw8Sg4AdKXuRQCMVk50dKCQUCwCAMYQECIAnF30TG4ASn1aIRIVjnQu9halxagDXr45AUHaohIADFAx1oklpfBIKOiYOPjEfrldHU5F002t7Zc0s4PBOhJTpbikAGaKUADKQzeUFGViKX1+cCgAAUbDFAUlSBAAG6KJxWKy1AD0WKgzRSKCglw2C38UEQ6RAdXA0C4UjAvmJrjubU63X2qSOGVO2X8tAqaycNWpDT6EDkUlw3hEdIZEBoXCBqz0hhM5iK7iVun0RjMlhsk2qrkVr2VFghf3+N0+Pz+fThUDFEqlMvpvhofSKHxmGiK-yNSXctWDwfq0E09idkulsvdsYgxJqQA)

reference:[create tuple with more than 1000 length](https://dev.to/tylim88/typescript-exceed-recursion-limitation-18pm)

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

```ts
type RebuildTuple<T extends unknown> ={ [K in keyof T] : T[K] }
```
[playground](https://www.typescriptlang.org/play?#code/C4TwDgpgBAwgThAhsCBBOdEgOoEtgAWAMhAHYDmhAGgDwBQUjURAogHIDiAKgBJQQAPFKQAmAZyikArgFsARhDgAaBk1QwY-IWXFQppANakA9gHdSAbQC6UALxRrKgHx2o6mBYDkAGzKUCnjaCwrqsnLyqjAD8bhqRUABcsAjIaBhYeIQkFNQ0Ydw8Sg4AdKXuRQCMVk50dKCQUCwCAMYQECIAnF30TG4ASn1aIRIVjnQu9halxagDXr45AUHaohIADFAx1oklpfBIKOiYOPjEfrldHU5F002t7Zc0s4PBOhJTpbikAGaKUADKQzeUFGViKX1+cCgAAUbDFAUlSBAAG6KJxWKy1AD0WKgzRSKCglw2C38UEQ6RAdXA0C4UjAvmJrjubU63X2qSOGVO2X8tAqaycNWpDT6EDkUlw3hEdIZEBoXCBqz0hhM5gmAG8HABpKBfKAGCAgYzfKBcGxJLgWbU2AC+tXq0E09jFEqlMvpvgVnogxJqOKYAD0onQgA)
no error
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2zoquui6zk0c04ynb71l.png)

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

```ts
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])
//^?
```
[playground](https://www.typescriptlang.org/play?#code/C4TwDgpgBAShBGBXAlgGwCYBVFlRAPJlBAB7AQB26AzlIhQNYUD2A7hQDRQCCAwr8TKUadRi3YBtALoBeKNKgA+OUVLkqtCcgoAzCACcoAZS4A6c9r2GYUqAH5YCFBmy4CMDhPOm+vDkalFAC4efgBYAChQSEckNCwcPABGQkF1EXomNgppRSg5AG95AGkobSgGCBBmHShMKRDMCWLbAF9IjqjwaG582OcEt3wJJI4AJg4AZkDIgHpZqEWAPTtI6J6kvrg4l0SIFJHxqZmI+cWoFc6AY2YKamAoAEN4K5lUtWFaTPEcwIAKABuQVUQg0UAoEABBnsdSgIW2A1ceEIigAlDJFAV2hEbncHs8rkk3iD0l8xNlcoDgWlPuDIdCHER4U54kj9ij0ZjsZECX9DhNpqi5rNLhECUk+aMBVIhacRXYgA)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ao4wtl4kiw54zk3fg8pk.png)

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

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

```ts
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])
//^?
```

[playground](https://www.typescriptlang.org/play?#code/C4TwDgpgBAShBGBXAlgGwCYBVFlRAPJlBAB7AQB26AzlIhQNYUD2A7hQDRQCCAwr8TKUadRi3YBtALoBeKNKgA+OUVLkqtCcgoAzCACcoAZS4A6c9r2GYUqAH5YCFBmy4CMDhPOm+vDkalFAC4efgBYAChQSEckNCwcPABGQkF1EXomNgppRSgVNOFNKEsDYw5vUutbBwBveQBpEoooBggQZh15E28bWxCJHvMbCQbbAF8oEIoIADcDSMWo8GhufNjnBLd8CSSOACYOAGZAyIB6M6grgD07SOjVpPW4OJdEiBTdg+PTiIurqC3JYAY2YFGowCgAEN4MCZKk1EVRFlJIEABSzIKqIQaKAzeaGBxEEIvTauPCERQAShkilq40ioPBkJhwKS8Ox6VomXEOXRmM5SPxZSJUw28XJH0pNLpDIikVZaK+hxOVPOZyBEVZSSVexVUjVfw1diAA)

the hint doesn't look pretty
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9we89s0ksytiyvukdy3p.png)

but they are indeed the same thing

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jnvu1fy8noe03xmkhdof.png)