Template Literal Types and infer
As your TypeScript skills grow, you will encounter scenarios where you need to parse string combinations or extract types from nested structures. This is where Template Literal Types and the infer keyword shine.
1. Template Literal Types
Template literal types build on string literal types. They allow you to combine and manipulate strings at the type level, using the same syntax as JavaScript template strings.
type World = "world";
// Type evaluates to "hello world"
type Greeting = `hello ${World}`;Generating Combinations
When unions are passed into template literals, TypeScript generates all possible combinations:
type Vertical = "top" | "bottom";
type Horizontal = "left" | "right";
// Evaluates to: "top-left" | "top-right" | "bottom-left" | "bottom-right"
type Alignment = `${Vertical}-${Horizontal}`;This is highly useful for styling systems and configuration mapping.
2. Type Inference with infer
The infer keyword can only be used within the conditional check of a conditional type. It allows you to declare a placeholder type variable to be extracted by the compiler.
Extracting Promise Values
Suppose you want to extract the resolution type of a Promise:
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type ResolvedNumber = UnwrapPromise<Promise<number>>; // Evaluates to number
type DirectValue = UnwrapPromise<string>; // Evaluates to stringIn this example, if T is a Promise, TypeScript infers the wrapped type and names it U, then returns U.
3. Real-world Example: Function Return Types
TypeScript uses infer to define its built-in utility types, such as ReturnType.
type GetReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
function processOrder() {
return { orderId: 101, status: "pending" };
}
// Extract the return type of the function
type OrderResult = GetReturnType<typeof processOrder>;4. Summary
- Template literal types allow string manipulation and combinatorial matching during compilation.
- Use template literal unions to construct custom configuration keys.
- The
inferkeyword extracts nested types within conditional type checks. - Built-in helper types like
ReturnTyperely oninferto inspect function signatures.