String to Number

Challenge

Convert a string literal to a number, which behaves like Number.parseInt.

Solution

Um einen String in eine Nummer umzuwandeln, sollten wir erstmal alle String abfangen, die keine Nummer enthalten (z.B. ‘18@7_$%’). Hier gibt es zwei Möglichkeiten:

  1. Den String als Ganzes inferen und mit der Kondition versehen, dass es sich um eine Nummer handeln muss (https://devblogs.microsoft.com/typescript/announcing-typescript-4-8-beta/#infer-types-template-strings)
S extends `${infer N extends number}` ? ... : never
  1. Den erwünschten Typ einfach angeben
   S extends `${number}` ? ... : never

Entscheidet man sich für die erste Variante, ist die vollständige Lösung sehr simpel:

type ToNumber<S extends string> = S extends `${infer N extends number}`
  ? N
  : never;

Für Variante zwei wird es komplexer, da wir nun so lange Elemente in einen Akkumulator stecken, bis dessen Länge der Zahl (als String) entspricht. Wir vergleichen somit die Länge des Akkumulators als String mit der Nummer als String.


// Bei `24`:
// Erste Durchlauf => ['1']   // Acc-Length: `1`
// Zweiter Durchlauf => ['1', '1']   // Acc-Length: `2`
...
// N-ter Durchlauf => ['1', '1', '1', ... , '1']   // Acc-Length: `24` => entspricht Zahl als String `24`, also geben wir Acc['length'] => 24 zurueck.

type ToNumber<
  S extends string,
  Acc extends string[] = []
> = S extends `${number}`
  ? `${Acc["length"]}` extends S
    ? Acc["length"]
    : ToNumber<S, [...Acc, "1"]>
  : never;

References

Infer types template string