Hone logo
Hone
Problems

Type-Level String Manipulation: Extracting and Concatenating

Type-level programming in TypeScript allows you to perform operations on types themselves, rather than values at runtime. This challenge focuses on creating type-level functions to manipulate strings represented as types. Specifically, you'll implement functions to extract a substring and concatenate two string types, demonstrating the power of conditional types and utility types. This is useful for tasks like generating type-safe API endpoints based on configuration or creating specialized types based on string patterns.

Problem Description

You are tasked with creating two type-level functions: substring and concatenate.

  • substring<T extends string, Start extends number, Length extends number>: This function should extract a substring of length Length starting at index Start from the string type T. The result should be a new string type. If Start or Length are out of bounds, return an empty string type (""). Note that TypeScript string indices are 0-based.

  • concatenate<T extends string, U extends string>: This function should concatenate the string types T and U into a single string type.

Key Requirements:

  • Both functions must operate entirely at the type level, without runtime execution.
  • The functions should be generic, accepting string types and number types as arguments.
  • Error handling for out-of-bounds indices in substring is crucial.
  • The functions should be type-safe, ensuring that the input types are valid strings and numbers.

Expected Behavior:

The functions should produce the expected string types based on the input types. Incorrect indices or invalid types should result in appropriate type errors or empty string types.

Edge Cases to Consider:

  • Start is negative.
  • Start is greater than or equal to the length of T.
  • Length is negative.
  • Length is greater than the remaining length of T starting from Start.
  • Empty string types as input.
  • Zero length substring.

Examples

Example 1:

type Result1 = substring<"abcdefg", 2, 3>; // "cde"

Explanation: Extracts 3 characters starting from index 2 ("c", "d", "e") from "abcdefg".

Example 2:

type Result2 = substring<"abcdefg", 5, 2>; // "fg"

Explanation: Extracts 2 characters starting from index 5 ("f", "g") from "abcdefg".

Example 3:

type Result3 = substring<"abcdefg", 2, 10>; // ""

Explanation: Length (10) is greater than the remaining length of the string starting from index 2. Returns an empty string.

Example 4:

type Result4 = substring<"abcdefg", -1, 3>; // ""

Explanation: Start is negative. Returns an empty string.

Example 5:

type Result5 = concatenate<"hello", " world">; // "hello world"

Explanation: Concatenates "hello" and " world" to produce "hello world".

Example 6:

type Result6 = concatenate<"", "typescript">; // "typescript"

Explanation: Concatenates an empty string with "typescript" to produce "typescript".

Constraints

  • All input types must be valid string types or number types.
  • Start and Length must be non-negative integers.
  • The functions should be implemented using TypeScript's type system features (conditional types, utility types, etc.).
  • Performance is not a concern, as these operations are performed at compile time.

Notes

  • Consider using conditional types to handle out-of-bounds scenarios in substring.
  • You might find it helpful to define smaller, reusable type-level utility functions to build up the more complex functions.
  • Think about how to represent string indices and lengths as types.
  • The goal is to create type-safe and expressive type-level functions. Focus on correctness and clarity over extreme optimization.
Loading editor...
typescript