DEV Community

Cover image for Breaking down an advanced Typescript type!
Arnau Espin
Arnau Espin

Posted on • Edited on

Breaking down an advanced Typescript type!

Introduction

Hello and welcome to my post about breaking down some advanced types in typescript!

On this example we have a Type which receives a string of a number "12" and provides 12.

type Twelve = StringToNumber<"12"> // 12
Enter fullscreen mode Exit fullscreen mode

Code

type StringToNumber<
  Len extends string,
  Arr extends unknown[] = []
> = `${Len}` extends `${Arr["length"]}`
  ? Arr["length"]
  : StringToNumber<Len, [...Arr, unknown]>;

type One = StringToNumber<"1"> // 1
Enter fullscreen mode Exit fullscreen mode

So, wtf did we just read? Well, it is a type that takes a string and its output is that string parsed to a number.

So let's suppose we have:

type One = StringToNumber<"1"> // 1
Enter fullscreen mode Exit fullscreen mode
// 1st time this type is used by `type One = StringToNumber<"1">`
type StringToNumber<
  Len extends string, // The string we are passing "1". It is a generic that we restrict to 'string' using the 'extends' keyword.
  Arr extends unknown[] = [] // Another generic, in this case an array of unknown which by default is an empty array.
> = `${Len}` extends `${Arr["length"]}` // Is the template literal `1` == `[].length` ? At the start, the Arr is an empty array, so the length is 0. So 1 extends 0 is false. Think about extends in this case as '==' .
  ? Arr["length"] // If so, we return the length of the array.
  : StringToNumber<Len, [...Arr, unknown]>; // Else, we call again (recursive) the StringToNumber type and we pass the 2 generic types: Len="1" and the Arr which at the moment is [unknown], since [...Arr, unknown] becomes [unknown] due to spreading Arr which is an empty array.

// The 2nd iteration, called by the recursivity from the previous statement.
type StringToNumber<
  Len extends string, // The string we are passing "1" (again)
  Arr extends unknown[] = [] // Now we are actually passing an array, which at the moment is [unknown] of length 1.
> = `${Len}` extends `${Arr["length"]}` // `1` == [unknown].length ? Now this is true, because Arr.length is 1
  ? Arr["length"] // Now, we return the length of the array, which is 1
  : StringToNumber<Len, [...Arr, unknown]>; 

Enter fullscreen mode Exit fullscreen mode

Conclusion

Typescript complex types can be sometimes hard to read, no doubt on that, although if they are broken down step by step can become somewhat clear.

You can follow me on:

Top comments (2)

Collapse
 
androbro profile image
koen de vulder

Great use of extension methods!

Thanks for sharing

Collapse
 
aspnxdd profile image
Arnau Espin

ty ser