# TypeScript Type Challenge TupleToObject Walkthrough

The goal of the challenge is to implement a generic type called TupleToObject, that transforms the tuple type passed to it into a object type where key and value are both elements from the tuple.

The challenge: https://github.com/type-challenges/type-challenges/blob/main/questions/00011-easy-tuple-to-object/README.md

## Watch the video

## An example case

For example, given the following interface, our TupleToObject should generate this type.

`const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const`

type result = TupleToObject<typeof tuple> // expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}

## Approach

Like in the Pick challenge, we need to create a new type based off an existing type, so therefore we can use a mapped types to do so.

Since we want our object type to contain key value pairs that both correspond to one entry in our readonly tuple, we could implement it like so:

`type TupleToObject<T extends readonly any[]> = {`

[Property in T]: Property

}

If this worked, it would create a new object type, with each key being `Property`

and each value being `Property`

, making our test cases pass.

## The solution

Unfortunately this doesn't work as mapped types can only be used against union types, not readonly tuple types.

So we need to convert our `readonly[]`

type into a union type, and then loop over this union type.

We know that given for any `readonly[]`

we could construct it's union type by taking the type of the first element, the second, the third all the way up to the nth, like:

`const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const`

const TupleType = typeof tuple

type union = TupleType[0] | TupleType[1] | TupleType[2] // etc

This works as we can use index types to access the types of each element in the `readonly[]`

.

This works, but we need to know the length of our tuple upfront, instead we can use the `TupleType[number]`

syntax to generate a union of all of the types in a `readonly[]`

tuple.

Using `T[number]`

to convert our readonly array into a union type, and mapping over that union looks like:

`type TupleToObject<T extends readonly any[]> = {`

[Property in T[number]]: Property

}

Finally, we need to constrain the type of readonly arrays that we accept. Since at the moment you can pass:

`const t = TupleToObject<[[1, 2], {}]>`

without the TypeScript compiler complaining, but clearly our `TupleToObject`

type can't work on this type since `[1, 2]`

and `{}`

aren't valid keys in a typescript type.

We need to restrict our `any[]`

type to be only tuples that contain elements that are valid keys. Valid keys in typescript can be `string`

, `number`

or `symbol`

so our final type becomes:

`type TupleToObject<T extends readonly (string | number | symbol)[]> = {`

[Property in T[number]]: Property

}