tezvyn:

TypeScript: Build New String Types with Template Literals

AI-drafted, machine-checkedSource: typescriptlang.orgadvanced

Template literal types are a factory for new string types, built from existing string literals and unions. They are perfect for generating permutations, like creating 'propChanged' event names from an object's keys.

WHY IT EXISTS Manually defining large sets of related string literal types is tedious and error-prone. For example, if you have 10 event names and 5 languages, you'd have to write out 50 unique type variations. Template literal types were created to generate these sets programmatically at the type level, ensuring correctness and eliminating boilerplate.

THE MENTAL MODEL Think of it as string interpolation, but for your type system. Instead of creating a string value at runtime with ${...}, you are creating a new string literal type at compile time. It takes base types as building blocks and constructs a new, more complex type from them.

HOW IT WORKS Template literal types use the same backtick syntax (`) as JavaScript strings, but in a type position. When you interpolate a union type, TypeScript creates a new union type representing the cross-product of all possible string combinations. For example, type Color = 'red' | 'blue'; type Side = 'left' | 'right'; type T = {Color}-{Side}; results in the type 'red-left' | 'red-right' | 'blue-left' | 'blue-right'`.

WHEN TO USE IT This is powerful for creating strongly-typed event names based on an object's keys (e.g., on('firstNameChanged', ...)), generating all possible API route strings, or building comprehensive internationalization (i18n) key types from language codes and message IDs. It excels in cases with a small, predictable number of combinations.

WHEN NOT TO USE IT Avoid using template literals with very large unions or when interpolating multiple unions. The number of resulting types grows multiplicatively, which can create massive union types that cripple editor performance and significantly slow down the TypeScript compiler. For these scenarios, ahead-of-time code generation is a better strategy.

ONE CANONICAL EXAMPLE Consider a function that adds an event listener method on() to an object. With template literals, you can type the event name to be a key of the object with "Changed" appended. For an object with { name: string, age: number }, the event type would be 'nameChanged' | 'ageChanged'. This allows TypeScript to catch errors like on('emailChanged', ...) at compile time, because 'email' is not a key on the original object.

Read the original → typescriptlang.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.