# Building the Flatten Type with Typescript: A Tutorial for Beginners Typescript learning can be challenging but rewarding. To improve your understanding and skills, you can try building types and analyzing them piece by piece.

In this post we'll build a `Flatten` type.

The `Flatten` type is a utility type that takes an array of arrays and flattens it into a single array. It can be used to simplify the process of working with nested arrays.

``````type Flattened = Flatten<[1, 2, [3, 4], [[]]]>
// [1, 2, 3, 4, 5]``````

We have to somehow look inside the input array recursively, and spread any elements we find to be arrays.

Let's see how to do it step by step:

First, define the `Flatten` type as a generic type. It needs to take a type parameter which is the array we will provide when using the type.

``````type Flatten<T extends any[]> =
// implementation goes here``````

With `T extends any[]` we enforce the parameter `T` to be of type `any[]` .

Next, we're going to "look into" the array and get the values. We can do this with the `infer` keyword, which is used in the context of a conditional (`extends` keyword).

``````type Flatten<T extends any[]> = T extends [...infer S] ? S : [];

type Test = Flatten<[1, 2]> // this is just going to be [1, 2]``````

The spread operator (the 3 dots in `...infer S` ) means that we are "grabbing" all values inside the array, not just one.

For the false branch let's simply return `[]`, as it is the case of `T` being an empty array.

Now, we want to look at the values inside the input array one by one, and check if they are arrays or not, because if they are arrays we want to flatten them. To do this, we can split the contents of the array into two inferred types: `First` and `Rest` :

``````type Flatten<T extends any[]> = T extends [infer First, ...infer Rest]
? First
: [];

type Test = Flatten<[1, 2]>; /* this will now be 1, as the type is only
returning the first value in the array */``````

Here we used tuple destructuring.

Now let's check if the first element is an array. We need a conditional, which in typescript is done with `extends` .

``````type Flatten<T extends any[]> = T extends [infer First, ...infer Rest]
? First extends unknown[]
? // true branch, First is an array
: // false branch, First is not an array
: [];``````

In the true branch, `First` is an array, so we want to recursively call the `Flatten` type (we want to flatten it):

``````type Flatten<T extends any[]> = T extends [infer First, ...infer Rest]
? First extends unknown[]
? Flatten<First>
: // false branch, First is not an array
: [];``````

In the false branch, we could try to just use `First` without the need to flatten it. Let's try it:

``````type Flatten<T extends any[]> = T extends [infer First, ...infer Rest]
? First extends unknown[]
? Flatten<First>
: First
: [];``````

You might be noticing something. Right now, all this type is doing is returning only the `First` element of the array. What about the `Rest` of the array? We're never doing anything with it. When `First` is an array, it makes sense to spread the `First` along with the `Rest` like so:

``````type Flatten<T extends any[]> = T extends [infer First, ...infer Rest]
? First extends unknown[]
? Flatten<[...First, ...Rest]>
: First
: [];``````

What about when `First` is not an array? How to take into account the `Rest`

Can we do this?

``````type Flatten<T extends any[]> = T extends [infer First, ...infer Rest]
? First extends unknown[]
? Flatten<[...First, ...Rest]>
: [First, ...Rest]
: [];``````

No. It is obvious that `[First, ...Rest]` will result in the same input array. This is not enough. `Rest` is the same input array minus the `First` element, which has already been processed. Even if the `First` element is not an array, we need to recursively check the `Rest` of the array elements to check which ones are arrays.

How can we continue flattening the `Rest` of array elements?

Any idea comes to mind?

Yes, we can just use the type we're creating!

``````type Flatten<T extends any[]> = T extends [infer First, ...infer Rest]
? First extends unknown[]
? Flatten<[...First, ...Flatten<Rest>]>
: [First, ...Flatten<Rest>]
: [];``````

This might look slightly convoluted at this point, but `Flatten<Rest>` is taking the first element of the `Rest` array and flattening it. This is done recursively until `Rest` is an empty array or, what is the same, until all elements of the `T` array have been processed.

Now we can verify that the type works, for example, with:

``````type Flattened = Flatten<[1, 2, [3, 4], [[]]]>
// [1, 2, 3, 4, 5]``````

I hope this tutorial has helped you understand how to build the Flatten type with typescript. Happy coding!