Ts Template Literal
Template literal types are built based 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 like event names, paths, class names, etc.
* * *
* * *
## Why Template Literal Types Are Needed
In development, we often need to handle formatted strings, such as event names (onClick), API paths (get:/users), CSS class names (btn-primary-md), etc.
Using regular string types cannot accurately describe these formats, while template literal types allow us to precisely define the types of these strings.
This significantly 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's template strings but used at the type level.
* * *
## Basic Syntax
Template literal types are defined using backticks and interpolation.
## Example
// Define basic string literal types
type World ="world";
// Use template literal types
// `Hello ${World}` is equivalent to "Hello world"
type Greeting = `Hello ${World}`;
// Can only assign strings that match the defined type
var greeting: Greeting ="Hello world";
console.log("Greeting: "+ greeting);
**Output Result:**
Greeting: Hello world
> **Explanation:** Template literal types replace the interpolation positions with actual strings to generate new literal types.
* * *
## Built-in Utility Types
TypeScript provides four built-in utility types for handling string cases.
## Example
// Uppercase: Convert string to uppercase
type UpperHello = Uppercase;// "HELLO"
// Lowercase: Convert string to lowercase
type LowerHELLO = Lowercase;// "hello"
// Capitalize: Capitalize first letter of string
type CapitalizedHello = Capitalize;// "Hello"
// Uncapitalize: Lowercase first letter of string
type UncapitalizedHello = Uncapitalize;// "hello"
console.log("Uppercase: "+ UpperHello);
console.log("Lowercase: "+ LowerHELLO);
console.log("Capitalize: "+ CapitalizedHello);
console.log("Uncapitalize: "+ UncapitalizedHello);
**Output Result:**
Uppercase: HELLO Lowercase: hello Capitalize: Hello Uncapitalize: hello
> **Application Scenarios:** These utility types are very useful in scenarios where unified formatting is needed, such as event names and method names.
* * *
## Event Types
Template literal types can be used to precisely define the types of event names.
## Example
// Build event name types
// `on${Capitalize}` generates a string starting with "on", with the first letter capitalized
type EventName = `on${Capitalize}`;
// `handle${Capitalize}` generates a string starting with "handle", with the first letter capitalized
type Handler = `handle${Capitalize}`;
// 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 Result:**
Event: onClick Handler: handleSubmit
> **Advantage:** After using template literal types, incorrect formats like "onclick" (lowercase) will be rejected by TypeScript.
* * *
## Path Types
Template literal types can be used to precisely define API path types.
## Example
// Define HTTP method types
type HttpMethod ="get"|"post"|"put"|"delete";
// Define path format
type ApiEndpoint = `/${string}`;// String starting with a slash
// Combine into 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 Result:**
Path: /get/users Path: /post/users
> **Type Safety:** Paths like "/users" (without method prefix) will cause TypeScript to report an error.
* * *
## Complex Examples
Template literal types can combine multiple union types to generate all possible combinations.
## Example
// Template types with numbers
// ${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 Result:**
Class Name: btn-primary-md
> **Combination Explosion:** Template literal types automatically expand all combinations. If union types have many options, the generated types can become very large.
* * *
## Custom Utility Types
Custom template literal utility types can be created.
## Example
// Tool type to add prefix
// T is any string, P is the prefix to add
type Prefix= `${P}${Capitalize}`;
// Tool type to add suffix
// T is any string, S is the suffix to add
type Suffix= `${Capitalize}${S}`;
// Use custom utility types
type HandlerName = Prefix;
type ButtonId = Suffix;
var handler: HandlerName ="onClick";
var id: ButtonId ="SubmitBtn";
console.log("Handler: "+ handler);
console.log("ID: "+ id);
**Output Result:**
Handler: onClick ID: SubmitBtn
> **Generic Templates:** Template literal types can be combined with generics to create reusable utility types.
* * *
## Notes
* **Interpolation Types:** The `${}` in templates can be specific strings, union types, string, number, etc.
* **Combination Count:** When combining multiple union types, the generated types may become very large.
* **Case Handling:** Use built-in utility types to handle string case conversions.
> **Best Practices:** Use template literal types for strings with fixed formats like event names, paths, and class names to 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
* **Application Scenarios:** Event names, API paths, CSS class names, etc.
* **Customization:** Create reusable utility types
> **Recommendation:** In scenarios requiring formatted strings, prefer using template literal types for compile-time type checking.
* * *
YouTip