Template Literal Types

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 3 min

TL;DR

Template Literal Types build on JavaScript’s template literal strings (the backticks `). Instead of interpolating values into strings, they allow you to interpolate types into strings, generating massive amounts of string literal unions automatically.

Mental Model

How It Works

When a union type is interpolated into a template literal type, TypeScript calculates the cross-product of all possible combinations.
TypeScript also provides built-in intrinsic string manipulation types to help with this:

  • Uppercase<StringType>
  • Lowercase<StringType>
  • Capitalize<StringType>
  • Uncapitalize<StringType>

Example

type VerticalAlignment = "top" | "middle" | "bottom";
type HorizontalAlignment = "left" | "center" | "right";

// Calculates the 9 possible combinations!
type Alignment = `${VerticalAlignment}-${HorizontalAlignment}`;
/* Evaluates to: 
  | "top-left" | "top-center" | "top-right"
  | "middle-left" | "middle-center" | "middle-right"
  | "bottom-left" | "bottom-center" | "bottom-right"
*/

const position: Alignment = "bottom-center"; // Valid!


// --- GENERATING GETTER METHODS ---
type State = { id: number; name: string };

// We want an object that turns 'id' into 'getId' and 'name' into 'getName'
type Getters<T> = {
    [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
};

type StateGetters = Getters<State>;
/* Evaluates to:
{
    getId: () => number;
    getName: () => string;
}
*/

Common Interview Questions

How does extracting types from strings work with infer?

Template literal types are incredibly powerful when combined with infer inside conditional types. You can actually parse strings at compile time!

// Extracts the path from a URL
type ExtractPath<S extends string> = S extends `https://api.com/${infer Path}` ? Path : never;

type MyPath = ExtractPath<"https://api.com/users/123">; 
// Evaluates to: "users/123"