Home > Blockchain >  Proper way to create a Trim type
Proper way to create a Trim type

Time:10-19

I was reading the typescript 4.5beta blog post, the author implemented a TrimLeft utility type to show Tail-Recursion Elimination on Conditional Types , so I decided to implement a Trim utility type ( for learning purposes), my question is, what would you and how would you have done it differently?

type Trim<T extends string> =
    T extends 
        `${infer RestOne} ${infer RestTwo}` 
        ? Trim<`${RestOne}${RestTwo}`>
        : T extends ` ${infer RestThree} ${infer RestFour}`
           ? Trim<`${RestThree}${RestFour}`>
           : T extends ` ${infer RestFive} ${infer RestSix} `
             ? Trim<`${RestFive}${RestSix}`>
             : T extends `${infer RestSeven} ${infer RestEight} `
               ? Trim<`${RestSeven}${RestEight}`>
               : T;


type TestOne = Trim<" foo"> ; // "foo"
type TestTwo = Trim< " foo "> ; // "foo"
type TestThree = Trim<" foo bar "> ; // "foobar"
type TestThree = Trim<"   foo bar "> ; // "foobar"
type TestFour = Trim<"foo bar ">; // "foobar"

basically, it trims out all space in `Trim<T>`

CodePudding user response:

Consider this exmaple:

type Separator = ' ';

type Trim<T extends string, Acc extends string = ''> =
  (T extends `${infer Char}${infer Rest}`
    ? (Char extends Separator
      ? Trim<Rest, Acc>
      : Trim<Rest, `${Acc}${Char}`>)
    : (T extends ''
      ? Acc
      : never)
  )




type TestOne = Trim<" foo">; // "foo"
type TestTwo = Trim<" foo ">; // "foo"

type TestThree = Trim<" foo bar ">; // "foobar"
type TestThree2 = Trim<"   foo bar ">; // "foobar"
type TestFour = Trim<"foo bar ">; // "foobar"

Playground

Trim - iterates through the whole string. If it finds Separator (empty space) it just omits it and concats Acc with part of string without separator.

  • Related