Table of contents
Open Table of contents
Understanding Template Literal Types
Template Literal Types extend the capabilities of string literal types by allowing developers to create types that are formed by concatenating strings. This introduces a level of dynamism and pattern matching that was not possible with traditional string literal types. The syntax for Template Literal Types involves using backticks (`) to define template literals and the ${} syntax for inserting expressions.
type Greeting = `Hello, ${string}!`;
In the above example, Greeting is a Template Literal Type that matches any string that starts with “Hello, ” and ends with an exclamation mark.
Basic Examples
Let’s start with some basic examples to illustrate the fundamental concepts of Template Literal Types.
Example 1: Concatenating Strings
type Concatenate<T extends string, U extends string> = `${T}${U}`;
type Result = Concatenate<"Hello", "World">; // Result is 'HelloWorld'
In this example, the Concatenate type takes two string literal types (T and U) and concatenates them using the template literal type syntax.
Example 2: String Manipulation
type UppercaseFirstChar<S extends string> = `${Uppercase<S[0]>}${S.substring(1)}`;
type CapitalizedGreeting = UppercaseFirstChar<'hello'>; // CapitalizedGreeting is 'Hello'
Here, the UppercaseFirstChar type transforms a string by capitalizing its first character.
Advanced Use Cases
Template Literal Types truly shine when used in more advanced scenarios, such as creating mapped types and enforcing specific patterns.
Example 3: Generating Object Keys
type GenerateKeys<T extends string> = {
[K in T]: `${K}_key`;
};
type Keys = GenerateKeys<"one" | "two" | "three">;
// Keys is { one: 'one_key', two: 'two_key', three: 'three_key' }
In this example, the GenerateKeys type generates object keys based on the input string literal types.
Example 4.1: String Pattern Matching
type ExtractNumbers<S extends string> =
S extends `${infer Prefix}${number}${infer Suffix}` ? number : never;
type ExtractedNumber = ExtractNumbers<"user123">; // ExtractedNumber is 123
Here, the ExtractNumbers type extracts a number from a string pattern.
Example 4.2: String Pattern Matching
type sizeValue = number | `${number}px` | `${number}em` | `${number}rem`;
const sizeSomething = (value: sizeValue) =>
typeof value === "number" ? value + "%" : value;
sizeSomething(100); // 100%
sizeSomething("100px"); // 100px
sizeSomething("100vh"); // sizeSomething('100vh') // Error
Conclusion
TypeScript Template Literal Types provide a powerful mechanism for creating dynamic and pattern-based types, offering enhanced type safety and expressiveness. By leveraging template literal types, developers can craft more precise and flexible type definitions, leading to better code quality and maintainability. As TypeScript continues to evolve, Template Literal Types stand as a testament to the language’s commitment to empowering developers with advanced and expressive features.