๐ŸŽ“ A1Learner
๐Ÿ”
0 of 37 lessons completed

TypeScript Template Literal Patterns

Template literal patterns build a family of string types from shared parts, such as a prefix, a union, and a number slot. One pattern states every string the family allows.

Typed route strings from a pattern union

The entity union expands the route pattern into the routes for both resources. A second pattern adds a numeric id segment.

type Entity = 'users' | 'posts';
type ApiRoute = `/api/${Entity}` | `/api/${Entity}/${number}`;
const listRoute: ApiRoute = '/api/users';
const itemRoute: ApiRoute = '/api/posts/7';
console.log(listRoute);
console.log(itemRoute);

Unit-suffixed strings

Each alternative in the size pattern ends the number with a different unit. Both values carry a unit, so both assignments pass.

type CssSize = `${number}px` | `${number}%` | `${number}rem`;
const gapSize: CssSize = '12px';
const widthSize: CssSize = '50%';
console.log(gapSize);
console.log(widthSize);

Event names from a domain record

The pattern takes its first part from the keys of the domain record. The second part is a fixed action union.

interface Domain {
  user: { id: number };
  order: { total: number };
}
type EventName = `${keyof Domain & string}:${'created' | 'removed'}`;
const firstEvent: EventName = 'user:created';
const secondEvent: EventName = 'order:removed';
console.log(firstEvent);
console.log(secondEvent);

Example

type Page = 'home' | 'settings';
type PageRoute = `/${Page}`;
type PageEvent = `${Page}:opened`;
type CssSize = `${number}px` | `${number}%`;
const route: PageRoute = '/settings';
const evtName: PageEvent = 'settings:opened';
const padSize: CssSize = '8px';
console.log(route);
console.log(evtName);
console.log(padSize);

Key points

  • A union inside a pattern expands into one literal per union member.
  • A number slot in a pattern admits any digits while the text around them stays fixed.
  • Unit-suffixed patterns pair a number with a fixed unit, so a bare number string never fits.
  • Keys read from a record with keyof become the varying part of an event name pattern.
  • Values prove each pattern, since a string outside the family is refused at assignment.

In this example, one page union feeds both the route pattern and the event pattern, so the two families stay in step when a page is added. The size pattern guards the padding value in the same style.

Note

A pattern describes a set of literals, and the checker tests membership string by string.

Try it Yourself

Edit the code, then press Run.

Running is simulated ยท TypeScript Playground

Exercise

Which string fits the ApiRoute pattern from the first exhibit?