#1978Medium

Percentage Parser

Implement PercentageParser<T extends string>. Master advanced TypeScript type manipulation in this medium-level challenge on TypeScriptPro.

In this medium-level challenge, you'll implement a PercentageParser type that parses a percentage string like "+85%" into a tuple of three parts: the sign, the number, and the percent symbol.

Challenge Instructions: Percentage Parser

Medium

Implement PercentageParser<T extends string>. According to the /^(\+|\-)?(\d*)?(\%)?$/ regularity to match T and get three matches.

The structure should be: [plus or minus, number, unit] If it is not captured, the default is an empty string.

For example:

type PString1 = ""
type PString2 = "+85%"
type PString3 = "-85%"
type PString4 = "85%"
type PString5 = "85"
 
type R1 = PercentageParser<PString1> // expected ['', '', '']
type R2 = PercentageParser<PString2> // expected ["+", "85", "%"]
type R3 = PercentageParser<PString3> // expected ["-", "85", "%"]
type R4 = PercentageParser<PString4> // expected ["", "85", "%"]
type R5 = PercentageParser<PString5> // expected ["", "85", ""]

Change the following code to make the test cases pass (no type check errors).

ChallengeSolution
type Case0 = ['', '', '']
type Case1 = ['+', '', '']
type Case2 = ['+', '1', '']
type Case3 = ['+', '100', '']
type Case4 = ['+', '100', '%']
type Case5 = ['', '100', '%']
type Case6 = ['-', '100', '%']
type Case7 = ['-', '100', '']
type Case8 = ['-', '1', '']
type Case9 = ['', '', '%']
type Case10 = ['', '1', '']
type Case11 = ['', '100', '']

type cases = [
  Expect<Equal<PercentageParser<''>, Case0>>,
  Expect<Equal<PercentageParser<'+'>, Case1>>,
  Expect<Equal<PercentageParser<'+1'>, Case2>>,
  Expect<Equal<PercentageParser<'+100'>, Case3>>,
  Expect<Equal<PercentageParser<'+100%'>, Case4

Pro Challenge

Unlock 102+ medium, hard, and extreme challenges to master advanced TypeScript.

One-time payment. Lifetime access.

Detailed Explanation

type ParseSign<T extends string> =
  T extends `${infer S extends '+' | '-'}${string}` ? S : ''
 
type ParsePercent<T extends string> =
  T extends `${string}%` ? '%' : ''
 
type ParseNumber<T extends string> =
  T extends `${'+' | '-'}${infer N}` ? N : T extends `${infer N}` ? N : ''
 
type RemovePercent<T extends string> =
  T extends `${infer N}%` ? N : T
 
type PercentageParser<T extends string> = [
  ParseSign<T>,
  RemovePercent<ParseNumber<T>>,
  ParsePercent<T>,
]

How it works:

Alternatively, you can write a more concise version that handles sign and body in a single step:

type PercentageParser<T extends string> =
  T extends `${infer S extends '+' | '-'}${infer Rest}`
    ? [S, ...ParseBody<Rest>]
    : ['', ...ParseBody<T>]
 
type ParseBody<T extends string> =
  T extends `${infer N}%` ? [N, '%'] : [T, '']

This challenge helps you understand template literal type decomposition and how to apply multi-step string parsing at the type level in real-world scenarios.

This challenge is originally from here.

Share this challenge

Learn the Concepts