TypeScript

TypeScript Template Literal Types👨‍💻

Template literal types let you build string types using the same backtick syntax you use for runtime template strings. They turn TypeScript's type system into a string-processing engine: you can generate unions of every valid CSS class name, derive event handler names from event types, enforce URL patterns at compile time, and parse string shapes with infer. They shipped in TypeScript 4.1 and are one of the features that separate TypeScript from "JavaScript with annotations."

Key Takeaways

  • 1Template literal types use backtick syntax in type position — `` `on${Capitalize<Event>}` `` produces `"onClick" | "onFocus"` from a union
  • 2When you interpolate a union, TypeScript computes the cross product of all combinations — two unions of 5 members each produce 25 string literal types
  • 3Four intrinsic string types (`Uppercase`, `Lowercase`, `Capitalize`, `Uncapitalize`) are built into the compiler for type-level case transformations
  • 4Template literals combined with `infer` enable pattern matching on string shapes — you can extract route parameters, strip prefixes, or parse dot-paths
  • 5Mapped types with template literal key remapping (`as` clause) let you reshape entire object types by transforming their keys
  • 6The cross product grows multiplicatively — three unions of 10 members each produce 1,000 types, so keep interpolated unions small

Master typescript template literal types

Take the TypeScript Type System Mastery course with hands-on lessons and challenges.

Examples

Type-safe CSS utility classes

typescript

This is the pattern Tailwind CSS type definitions use internally. The compiler generates every valid combination from the union cross product, so typos like "mz-3" are caught before your code ever runs. The 60 members are fine for performance — problems only start with thousands.

Type-safe event emitter with handler derivation

typescript

The `as` clause in the mapped type remaps each key from "userLogin" to "onUserLogin" using Capitalize and a template literal. The payload type stays correctly linked to each event. This is the same pattern React uses for its synthetic event handler props.

API route builder with method and path enforcement

typescript

Each segment of the route is validated independently. You get autocompletion for every valid combination and compile errors for anything outside the defined unions. In a real codebase you would likely narrow the Method per resource (GET-only for some routes), but this shows the core pattern.

Environment variable parser with prefix stripping

typescript

This combines template literal pattern matching (infer to strip the prefix), intrinsic types (Capitalize, Lowercase, Uncapitalize), and recursion (SnakeToCamel processes each underscore-delimited segment). It is a realistic pattern for config modules that read from process.env and expose a typed object.

Typed i18n key paths with dot notation

typescript

This is how libraries like i18next and typesafe-i18n generate typed key paths from a translation object. The recursive type walks the object tree, building up the dot-separated path as a template literal. Every leaf node becomes a valid key, and anything else is a compile error.

Intrinsic string types in action

typescript

The four intrinsic types are compiler-level primitives, not user-defined conditional types, so they are fast. Capitalize and Uncapitalize touch only the first character; Uppercase and Lowercase transform the entire string. They distribute over unions automatically, making them ideal building blocks for template literal transformations.

Common Mistakes

Mistake:

Interpolating large unions and getting a combinatorial explosion — e.g., three unions of 20 members each produces 8,000 types and tanks compiler performance

Fix:

Keep interpolated unions under 10 members each. If you need broad string validation (like all valid hex colors), use a branded string type with runtime validation instead of trying to enumerate every possibility in the type system.

Mistake:

Using `Uppercase` when you meant `Capitalize` — `Uppercase<"hello">` gives `"HELLO"`, not `"Hello"`

Fix:

Use `Capitalize` to uppercase only the first letter (for camelCase, PascalCase, handler names). Use `Uppercase` when you want the entire string transformed (for constants, HTTP methods, enum-like values).

Mistake:

Trying to interpolate object types or symbols in template literals — only `string`, `number`, `bigint`, `boolean`, `null`, and `undefined` are valid

Fix:

When iterating over keys, use `keyof T & string` to filter out numeric and symbol keys before interpolating. This is especially important in mapped types with key remapping.

Mistake:

Assuming template literal types provide runtime validation — they are erased at compile time like all TypeScript types

Fix:

Pair template literal types with a runtime check when accepting external input. Use them for internal API contracts and developer-facing signatures, not for validating user-supplied strings.

Best Practices

  • Use template literal types for closed sets of known strings — CSS classes, event names, route paths, config keys — where the combinatorial space is bounded and manageable
  • Combine `Capitalize` with the `on` prefix for event handler naming; this is the standard TypeScript convention that React, Vue, and most UI libraries follow
  • Use key remapping (`as` clause in mapped types) with template literals to reshape object types — it is cleaner than building a new type from scratch
  • When recursive template literal types get complex (more than two levels of `infer`), add a comment explaining the pattern — your future self and teammates will thank you
  • Prefer intrinsic string types over manual conditional types for case transformations — `Capitalize<T>` is faster and more readable than a custom `MyCapitalize<T>` built with `infer`

Summary

Template literal types bring string interpolation to the type system. They generate union cross products from backtick syntax, transform strings with Capitalize, Uppercase, Lowercase, and Uncapitalize, and parse string shapes with `infer`. The sweet spot is typed CSS classes, event systems, route builders, and config parsers — anywhere you have a finite, structured set of string values. Keep interpolated unions small to avoid compiler slowdowns, and remember that these types vanish at runtime.

Practice TypeScript with hands-on challenges

Learn typescript template literal types hands-on in your IDE

Interactive lessons and challenges on Stanza, practice in VS Code, Cursor, or the web.

Related Concepts

Related Cheatsheets

Master TypeScript with Stanza

Interactive lessons and challenges, right in your code editor.

Check the free courses. No credit card.