TypeScriptGenerics and advanced types
Template literal types
String types built from templates, like `${A}-${B}`.
Example
#TypeScript
type Size = 'sm' | 'md' | 'lg'
type Variant = 'primary' | 'ghost'
type ButtonClass = `btn-${Variant}-${Size}`
// type ButtonClass = "btn-primary-sm" | "btn-primary-md" | ... (6 combinations)
function buttonClass(variant: Variant, size: Size): ButtonClass {
return `btn-${variant}-${size}`
}
console.log(buttonClass('primary', 'lg'))Result
btn-primary-lg
Definition and usage
#Template literal types use JavaScript’s template syntax, but at the type level. `btn-${Size}` with Size = "sm" | "lg" gives the union "btn-sm" | "btn-lg". The compiler expands every combination.
This lets you precisely type CSS class names, event names, translation keys, or paths. A typo in a string like that gets caught right away.
TypeScript also has built-in types for changing letter case: Uppercase, Lowercase, Capitalize, and Uncapitalize, which come in handy combined with templates.
Syntax
#Syntax
type Name = `prefix-${Type}`More examples
#TypeScript
type Field = 'email' | 'password'
type ChangeEvent = `${Field}Changed`
// type ChangeEvent = "emailChanged" | "passwordChanged"
const event: ChangeEvent = 'emailChanged'
console.log(event)Result
emailChanged
Good practices
#- With large unions, the number of combinations grows fast. Too many combinations slow the compiler down.
- Template literal types work great for translation keys, e.g.
`nav_${string}`.
Related entries
#Spotted a mistake or missing an example? Write to us.