Template Literals in TypeScript

A new feature in TypeScript 4.1 is the ability to create Template Literal Types.

Template Literals in TypeScript
Photo by Sharon McCutcheon / Unsplash

A new feature in TypeScript 4.1 is the ability to create Template Literal Types. This feature allows you to use string interpolation to create types:

type World = "world";

type HelloWorld = `Hello ${World}`;

// type HelloWorld = "Hello world"

Looks interesting, right? This feature gets even more powerful when you combine it with union string literals:

type Vertical = "top" | "middle" | "bottom";
type Horizontal = "left" | "center" | "right";

type Position = `${Vertical}-${Horizontal}`;

declare function setPosition(pos: Position): void;


The union types are expanded to include every possible permutation! So we get access to top-center, bottom-right, top-left, and so on, and all the type safety that this brings. Hopefully you can see the potential here. For example, we can easily expand on this to add more options—I'm English, so we could add "centre" to the Horizontal type to enable a bit of localisation.

This example was lifted straight from the TypeScript release notes for Version 4.1, but I wanted to see what else I could come up with. Below is an example of using template literal types to create hex pairs, which we can then use in a makeColor function:

type HexNum = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
type HexLet = "a" | "b" | "c" | "d" | "e" | "f";
type HexChar = HexNum | HexLet;

type HexPair = `${HexChar}${HexChar}`;

// Stub
type Color = {};

declare function makeColor(
  r: HexPair,
  g: HexPair,
  b: HexPair,
  a?: HexPair
): Color;

makeColor("aa", "1a", "ff");
makeColor("ba", "da", "55", "e5");
makeColor("zz", "vv", "1j"); // error!

Here, we define all the possible hex characters, and then define a HexPair by using template literal types to join two HexChars together. We then use this type for each argument to the makeColor function, to enable type safety when passing in a hex pair.

Pretty neat!

The code for this post is available in this TypeScript playground.