Hone logo
Hone
Problems

Type-Level String Manipulation Utilities

Type-level programming allows us to perform operations on types as if they were values. This challenge focuses on creating a suite of utility types that manipulate strings at the type level. Building these utilities enhances type safety and enables powerful abstractions within your TypeScript code, allowing you to reason about string operations during compile time.

Problem Description

You are tasked with creating a set of type-level utility types for string manipulation. These utilities should operate on string types and produce new types representing the results of the manipulations. Specifically, you need to implement the following:

  1. Uppercase<T>: Converts a string type T to uppercase.
  2. Lowercase<T>: Converts a string type T to lowercase.
  3. Capitalize<T>: Capitalizes the first letter of a string type T.
  4. Uncapitalize<T>: Uncapitalizes the first letter of a string type T.
  5. ReplaceFirst<T, old, new>: Replaces the first occurrence of a substring old within a string type T with a substring new.
  6. Repeat<T, n>: Repeats a string type T n times, where n is a number type.

Key Requirements:

  • All utilities must be implemented using conditional types and other advanced TypeScript type features.
  • The utilities should be generic and work with any string type.
  • The Repeat utility must handle the case where n is 0 correctly (returning an empty string type).
  • The ReplaceFirst utility should return the original string if old is not found.

Expected Behavior:

The type system should infer the correct results based on the input types. For example, Uppercase<"hello"> should infer to "HELLO".

Edge Cases to Consider:

  • Empty strings: How should each utility behave with an empty string input?
  • ReplaceFirst with old not present: Should it return the original string?
  • Repeat with n being 0: Should it return an empty string type?
  • Capitalize and Uncapitalize with already capitalized/uncapitalized strings.

Examples

Example 1:

type UppercaseResult = Uppercase<"hello">; // "HELLO"

Explanation: The Uppercase utility converts the string "hello" to uppercase at the type level.

Example 2:

type RepeatResult = Repeat<"hello", 3>; // "hellohellohello"

Explanation: The Repeat utility repeats the string "hello" three times at the type level.

Example 3:

type ReplaceFirstResult = ReplaceFirst<"hello world", "world", "TypeScript">; // "hello TypeScript"

Explanation: The ReplaceFirst utility replaces the first occurrence of "world" with "TypeScript" in the string "hello world" at the type level.

Example 4:

type CapitalizeResult = Capitalize<"hello">; // "Hello"

Explanation: The Capitalize utility capitalizes the first letter of the string "hello" at the type level.

Example 5:

type UncapitalizeResult = Uncapitalize<"Hello">; // "hello"

Explanation: The Uncapitalize utility uncapitalizes the first letter of the string "Hello" at the type level.

Example 6:

type RepeatZeroResult = Repeat<"hello", 0>; // ""

Explanation: The Repeat utility repeats the string "hello" zero times, resulting in an empty string type.

Constraints

  • All utilities must be implemented using TypeScript's type system (conditional types, mapped types, etc.). No runtime code is allowed.
  • The n parameter in Repeat<T, n> must be a number type.
  • The old and new parameters in ReplaceFirst<T, old, new> must be string types.
  • The solutions should be reasonably efficient in terms of type complexity. Avoid excessively complex or deeply nested type structures where simpler alternatives exist.

Notes

  • Consider using distributive conditional types to handle union types correctly.
  • The Capitalize and Uncapitalize utilities can be implemented using a combination of conditional types and string manipulation techniques at the type level.
  • The ReplaceFirst utility is the most challenging and may require a recursive approach or clever use of conditional types to find and replace the first occurrence of the substring.
  • Think about how to handle edge cases gracefully and ensure that your utilities behave as expected in all scenarios. Testing with various inputs, including empty strings and edge cases, is crucial.
  • Focus on creating reusable and well-typed utilities that can be easily integrated into other type-level programs.
Loading editor...
typescript