# Challenge 3: Type Challenges

March 22, 2022

Type challenges are a great way to practice using the TS type system. These are often quite challenging, but they give you valuable practice thinking about how utility types work.

Let’s tackle a curated selection of these challenges ourselves!

## Round 1

### `If<C, T, F>`

Implement a type that evaluates to `T` if the type `C` is `true` or `F` if `C` is `false`.

`ts`// Implement this typetype If<C, T, F> = never // Teststype cases = [  Expect<Equal<If<true, "apple", "pear">, "apple">>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  Expect<Equal<If<false, "orange", 42>, 42>>Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.]`Try`

### `LengthOfTuple<T>`

Implement a type that evaluates to a numeric type literal, equivalent to the length of a specified tuple type `T`

`ts`// Implement this typetype LengthOfTuple<T> = never // Testsconst Fruits = ["cherry", "banana"] as consttype cases = [  Expect<Equal<LengthOfTuple<[1, 2, 3]>, 3>>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  Expect<NotEqual<LengthOfTuple<[1, 2, 3]>, 2>>,  Expect<Equal<LengthOfTuple<typeof Fruits>, 2>>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  Expect<Equal<LengthOfTuple<[]>, 0>>Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.]`Try`

### `EndsWith<A, B>`

Implement a type that evaluates to `true` if the type `A` ends with the type `B`, otherwise false.

`ts`// Implement this typetype EndsWith<A, B> = any // Teststype cases = [  Expect<Equal<EndsWith<"ice cream", "cream">, true>>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  Expect<Equal<EndsWith<"ice cream", "chocolate">, false>>Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.]`Try`
Click for hints
`ts`type FirstLetter<S> = S extends `\${infer F}\${string}`  ? F  : neverlet firstLetterOfBird: FirstLetter<"bird">           let firstLetterOfBird: "b"let firstLetterOfDog: FirstLetter<"dog">           let firstLetterOfDog: "d"`Try`

### `Concat<A, B>`

Implement a type that concatenates two tuple types `A`, and `B`

`ts`// Implement this typetype Concat<A, B> = any // Teststype cases = [  Expect<Equal<Concat<[], []>, []>>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  Expect<Equal<Concat<[], ["hello"]>, ["hello"]>>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  Expect<    Equal<Concat<[18, 19], [20, 21]>, [18, 19, 20, 21]>Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  >,  Expect<    Equal<Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.      Concat<[42, "a", "b"], [Promise<boolean>]>,      [42, "a", "b", Promise<boolean>]    >  >]`Try`

## Round 2

### `ReturnOf<F>`

Implement a type that emits the return type of a function type `F`

`ts`// Implement this typetype ReturnOf<F> = never // Tests const flipCoin = () =>  Math.random() > 0.5 ? "heads" : "tails"const rockPaperScissors = (arg: 1 | 2 | 3) => {  return arg === 1    ? ("rock" as const)    : arg === 2    ? ("paper" as const)    : ("scissors" as const)} type cases = [  // simple 1  Expect<Equal<boolean, ReturnOf<() => boolean>>>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  // simple 2  Expect<Equal<123, ReturnOf<() => 123>>>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  Expect<    Equal<ComplexObject, ReturnOf<() => ComplexObject>>Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  >,  Expect<    Equal<Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.      Promise<boolean>,      ReturnOf<() => Promise<boolean>>    >  >,  Expect<Equal<() => "foo", ReturnOf<() => () => "foo">>>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  Expect<    Equal<"heads" | "tails", ReturnOf<typeof flipCoin>>Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  >,  Expect<    Equal<Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.      "rock" | "paper" | "scissors",      ReturnOf<typeof rockPaperScissors>    >  >] type ComplexObject = {  a: [12, "foo"]  bar: "hello"  prev(): number}`Try`

### `Split<S, SEP>`

Implement a type that splits a string literal type `S` by a delimiter `SEP`, emitting a tuple type containing the string literal types for all of the “tokens”

`ts`// Implement this typetype Split<S extends string, SEP extends string> = any // Tests type cases = [  Expect<    Equal<Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.      Split<"Hi! How are you?", "z">,      ["Hi! How are you?"]    >  >,  Expect<    Equal<Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.      Split<"Hi! How are you?", " ">,      ["Hi!", "How", "are", "you?"]    >  >,  Expect<    Equal<Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.      Split<"Hi! How are you?", "">,      [        "H",        "i",        "!",        " ",        "H",        "o",        "w",        " ",        "a",        "r",        "e",        " ",        "y",        "o",        "u",        "?"      ]    >  >,  Expect<Equal<Split<"", "">, []>>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  Expect<Equal<Split<"", "z">, [""]>>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  Expect<Equal<Split<string, "whatever">, string[]>>Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.]`Try`

### `IsTuple<T>`

Implement a type `IsTuple`, which takes an input type `T` and returns whether `T` is tuple type.

`ts`// Implement this typetype IsTuple<T> = any // Teststype cases = [  Expect<Equal<IsTuple<[]>, true>>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  Expect<Equal<IsTuple<[number]>, true>>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  Expect<Equal<IsTuple<readonly >, true>>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  Expect<Equal<IsTuple<{ length: 1 }>, false>>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  Expect<Equal<IsTuple<number[]>, false>>Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.]`Try`
Click for hints
`ts`type TypeExtends<A, B> = A extends B ? true : falselet t0: TypeExtends<number, 6>let t1: TypeExtends<6, number>`Try`

## Round 3

### `TupleToNestedObject<P, V>`

Given a tuple type `T` that only contains string type, and a type `U`, build an object recursively.

`ts`// Implement this typetype TupleToNestedObject<P, V> = any // Tests type cases = [  Expect<    Equal<TupleToNestedObject<["a"], string>, { a: string }>Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  >,  Expect<    Equal<Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.      TupleToNestedObject<["a", "b"], number>,      { a: { b: number } }    >  >,  Expect<    Equal<Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.      TupleToNestedObject<["a", "b", "c"], boolean>,      { a: { b: { c: boolean } } }    >  >,  Expect<Equal<TupleToNestedObject<[], boolean>, boolean>>Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.]`Try`
Click for hints
```ts```type Pets = "dog"type PetsObj = {  [K in Pets]: Promise<number>}let x: PetsObj         type PetsObj = {
dog: Promise<number>;
}```Try```

### `IndexOf<T, U>`

Implement the type version of `Array.indexOf`, `IndexOf<T, U>` takes an Array `T`, any `U` and returns the index of the first `U` in Array `T`.

`ts`// Implement this typetype IndexOf<T, U> = any // Tests type cases = [  Expect<Equal<IndexOf<[1, 2, 3], 2>, 1>>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  Expect<Equal<IndexOf<[2, 6, 3, 8, 4, 1, 7, 3, 9], 3>, 2>>,Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.  Expect<Equal<IndexOf<[0, 0, 0], 2>, -1>>Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.]`Try` Written by Mike North , Developer Experience Tech Lead at Stripe, and Frontend Masters Instructor. You should connect with him on LinkedIn or follow him on Twitter