TypeScript Type-Exercises 2

    Jan 4, 2024

    There are some type exercise about string literal type.

    Spilt String into Chars

    type Split<T extends string, U extends unknown[] = []> = T extends `${infer F}${infer Rest}`
      ? Split<Rest, [...U, F]>
      : U;
    
    type MyType = Split<"abcdef">;
    // MyType = ["a", "b", "c", "d", "e", "f"]
    

    Trim, TrimStart, TrimEnd

    type TWhiteSpace = " " | "\n" | "\t";
    
    type TrimStart<S extends string> = S extends `${TWhiteSpace}${infer R}` ? TrimStart<R> : S;
    type TrimEnd<S extends string> = S extends `${infer R}${TWhiteSpace}` ? TrimEnd<R> : S;
    type Trim<T extends string> = TrimRight<TrimLeft<T>>;
    
    type MyTrimEnd = TrimEnd<"Hello World   ">;
    // 'Hello World'
    type MyTrimStart = TrimStart<"  Hello World">;
    // 'Hello World'
    type MyTrim = Trim<"   Hello World   ">;
    // 'Hello World'
    

    Lowercase To Uppercase

    type LowercaseToUppercase<L extends string> = L extends `${"a"}${infer R}`
      ? `${"A"}${LowercaseToUppercase<R>}`
      : L extends `${"b"}${infer R}`
      ? `${"B"}${LowercaseToUppercase<R>}`
      : L extends `${"c"}${infer R}`
      ? `${"C"}${LowercaseToUppercase<R>}`
      : L extends `${"d"}${infer R}`
      ? `${"D"}${LowercaseToUppercase<R>}`
      : L extends `${"e"}${infer R}`
      : .....
      : L;
    
    type MyUppercase = LowercaseToUppercase<"hello">;
    // MyUppercase = "HELLO"
    

    With the akin method, we also make a UppercaseToLowercase type definition.

    Capitalize

    type Capitalize<S extends string> = S extends `${infer L}${infer R}` ? `${Uppercase<L>}${R}` : "";
    
    type MyType = Capitalize<"hello world">;
    // MyType = 'Hello world'
    

    Replace

    type Replace<S extends string, F extends string, T extends string> = F extends ""
      ? S
      : S extends `${infer L}${F}${infer R}`
        ? `${L}${T}${R}`
        : S;
    
    type MyType = Replace<"this is the test demo", "e", "E">;
    // MyType: 'this is thE test demo'
    

    It replace the first matched char.

    Replace All

    type ReplaceAll<S extends string, F extends string, T extends string> = F extends ""
      ? S
      : S extends `${infer L}${F}${infer R}`
        ? `${ReplaceAll<L, F, T>}${T}${ReplaceAll<R, F, T>}`
        : S;
    
    type MyType = ReplaceAll<"this is the test demo", "e", "E">;
    // MyType: 'this is thE tEst dEmo'
    

    Replace all matched chars.

    StartsWith && EndsWith

    type StartsWith<T extends string, U extends string> = T extends `${U}${string}` ? true : false;
    type EndsWith<T extends string, U extends string> = T extends `${string}${U}` ? true : false;
    
    type a = StartsWith<"abc", "ac">; // false
    type b = StartsWith<"abc", "ab">; // true
    type c = StartsWith<"abc", "abcd">; // false
    

    Repeat String

    type RepeatString<
      Input extends string,
      Count,
      AuxArr extends Input[] = [],
      Result extends string = "",
    > = AuxArr["length"] extends Count ? Result : RepeatString<Input, Count, [Input, ...AuxArr], `${Input}${Result}`>;
    
    type MyType = RepeatString<"hello", 3>;
    // 'hellohellohello'