TypeScript Template Literal Types
Template literal types are built on string literal types and support generating new string types through interpolation.
This allows TypeScript to perform more precise type checking on strings, suitable for scenarios such as event names, paths, and class names.
SVG Diagram: Template Literal Types
Why Do We Need Template Literal Types
In development, we often need to handle formatted strings, such as event names (onClick), API paths (get:/users), CSS class names (btn-primary-md), and so on.
The plain string type cannot precisely describe these formats, but template literal types allow us to precisely define the types of these strings.
This greatly enhances TypeScript's type safety and reduces runtime errors.
Concept Explanation:Template literal types use backticks (`` ` ``) and
${}interpolation syntax to define string types, similar to JavaScript template strings, but used at the type level.
Basic Syntax
Template literal types use backticks and interpolation to define types.
Example
type World = "world";
// Use a template literal type
// `Hello ${World}` is equivalent to "Hello world"
type Greeting = `Hello ${World}`;
// Can only assign strings that match the type definition
var greeting: Greeting = "Hello world";
console.log("Greeting: " + greeting);
Output:
问候: Hello world
Explanation:Template literal types replace the interpolation position with the actual string, generating a new literal type.
Built-in Utility Types
TypeScript provides four built-in utility types for handling string casing.
Example
type UpperHello = Uppercase<"hello">; // "HELLO"
// Lowercase: Converts a string to lowercase
type LowerHELLO = Lowercase<"HELLO">; // "hello"
// Capitalize: Capitalizes the first letter of a string
type CapitalizedHello = Capitalize<"hello">; // "Hello"
// Uncapitalize: Lowercases the first letter of a string
type UncapitalizedHello = Uncapitalize<"Hello">; // "hello"
console.log("Uppercase: " + UpperHello);
console.log("Lowercase: " + LowerHELLO);
console.log("Capitalize: " + CapitalizedHello);
console.log("Uncapitalize: " + UncapitalizedHello);
Output:
Uppercase: HELLO Lowercase: hello Capitalize: Hello Uncapitalize: hello
Use Cases:These utility types are very useful in scenarios that require unified formatting, such as event names and method names.
Event Types
Template literal types can be used to precisely define the types of event names.
Example
// `on${Capitalize<string>}` generates strings starting with "on" and capitalized first letter
type EventName = `on${Capitalize<string>}`;
// `handle${Capitalize<string>}` generates strings starting with "handle" and capitalized first letter
type Handler = `handle${Capitalize<string>}`;
// Can only assign strings that match the format
var clickEvent: EventName = "onClick";
var focusEvent: EventName = "onFocus";
var handler: Handler = "handleSubmit";
console.log("Event: " + clickEvent);
console.log("Handler: " + handler);
Output:
事件: onClick 处理器: handleSubmit
Advantages:With template literal types, incorrect formats like "onclick" (lowercase) will be rejected by TypeScript.
Path Types
Template literal types can be used to precisely define the types of API paths.
Example
type HttpMethod = "get" | "post" | "put" | "delete";
// Define path format
type ApiEndpoint = `/${string}`; // Strings starting with a slash
// Combine into a complete API path type
type ApiPath = `${HttpMethod}${ApiEndpoint}`;
// Can only assign paths that match the format
var getUsers: ApiPath = "/get/users";
var createUser: ApiPath = "/post/users";
console.log("Path: " + getUsers);
console.log("Path: " + createUser);
Output:
路径: /get/users 路径: /post/users
Type Safety:Paths like "/users" (without a method prefix) will be reported as errors by TypeScript.
Complex Example
Template literal types can combine multiple union types to generate all possible combinations.
Example
// ${number} matches any number
type Row = `row${number}`;
type Row10 = Row; // row0, row1, row2... up to row9...
// Combine multiple types
type Variant = "primary" | "secondary";
type Size = "sm" | "md" | "lg";
// This generates 6 combinations: btn-primary-sm, btn-primary-md, btn-primary-lg...
type ClassName = `btn-${Variant}-${Size}`;
// Can only assign one of the 6 generated combinations
var className: ClassName = "btn-primary-md";
console.log("Class name: " + className);
Output:
类名: btn-primary-md
Combination Explosion:Template literal types automatically expand all combinations. If the union types have many options, the generated type can become very large.
Custom Utility Types
You can create your own template literal utility types.
Example
// T is any string, P is the prefix to add
type Prefix<T extends string, P extends string> = `${P}${Capitalize<T>}`;
// Utility type for adding a suffix
// T is any string, S is the suffix to add
type Suffix<T extends string, S extends string> = `${Capitalize<T>}${S}`;
// Use custom utility types
type HandlerName = Prefix<"click", "on">;
type ButtonId = Suffix<"submit", "Btn">;
var handler: HandlerName = "onClick";
var id: ButtonId = "SubmitBtn";
console.log("Handler: " + handler);
console.log("ID: " + id);
Output:
处理器: onClick ID: SubmitBtn
Generic Templates:Template literal types can be combined with generics to create reusable utility types.
Notes
- Interpolation Types:In a template, the
${}can be specific strings, union types, string, number, etc. - Number of Combinations:When combining multiple union types, the generated type can be very large
- Case Handling:Use built-in utility types to handle string casing
Best Practices:Using template literal types to handle strings with fixed formats such as event names, paths, and class names can achieve better type safety.
Summary
Template literal types are part of TypeScript's powerful type system.
- Template Syntax:Use
${T}interpolation to build types - Built-in Utilities:Uppercase、Lowercase、Capitalize、Uncapitalize
- Use Cases:Event names, API paths, CSS class names, etc.
- Customization:Create reusable utility types
Recommendation:In scenarios requiring formatted strings, prioritize using template literal types to obtain compile-time type checking.
Other Extensions