Yuzhe's Blog

yuzhes

531. String to Union

531. String to Union

Challenge Link

Problem

Implement the StringToUnion type. Type takes a string argument. The output should be a union of input letters.

type Test = "123"
type Result = StringToUnion<Test> // expected to be "1" | "2" | "3"

Solution

type StringToUnion<S extends string> = 
  S extends `${infer First}${infer Rest}`
    ? First | StringToUnion<Rest>
    : never

Deep Dive

How It Works

This solution leverages TypeScript’s template literal types and conditional types to recursively decompose a string into its individual characters:

  1. Pattern Matching: S extends \inferFirst{infer First}{infer Rest}` uses template literal inference to extract the first character (First) and the remaining string (Rest`).

  2. Union Building: For each recursion step, we add First to the union with First | StringToUnion<Rest>.

  3. Base Case: When S is empty, the pattern match fails, returning never. Since T | never = T, this cleanly terminates the recursion.

Step-by-Step Example

For StringToUnion<"abc">:

StringToUnion<"abc">
= "a" | StringToUnion<"bc">
= "a" | "b" | StringToUnion<"c">
= "a" | "b" | "c" | StringToUnion<"">
= "a" | "b" | "c" | never
= "a" | "b" | "c"

Why infer Works With Single Characters

When you use ${infer First}${infer Rest} on a string:

Edge Cases

type Empty = StringToUnion<"">      // never
type Single = StringToUnion<"x">    // "x"
type Spaces = StringToUnion<"a b">  // "a" | " " | "b"

Key Takeaways

  1. Template Literal Inference: ${infer X}${infer Y} is the standard pattern for string decomposition in TypeScript’s type system.

  2. Recursive Union Construction: Building unions recursively with X | RecursiveType<Rest> is a common pattern for transforming sequences.

  3. never as Identity: In union types, never acts as the identity element — adding it changes nothing, making it perfect for base cases.

  4. Character-Level Operations: This pattern is foundational for many string manipulation types like Split, Join, and character filtering.