TypeScript Literal Types
Literal types narrow a primitive down to one exact value, letting TypeScript check that only a specific, known set of values is ever used.
What Are Literal Types?
Normally `string` accepts any string and `number` accepts any number. A literal type narrows that down to a single exact value, like `"GET"` or `200`. Literal types are rarely used alone - they're almost always combined into a union so a variable can hold one of a small, closed set of values, and TypeScript will reject anything outside that set.
Basic Literal Unions
let direction: "up" | "down" | "left" | "right";
direction = "up";
// direction = "north"; // Error: not assignable
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
function request(url: string, method: HttpMethod): void {
console.log(`${method} ${url}`);
}
request("/users", "GET");Literal Types with Discriminated Unions
Literal types become especially powerful when one property acts as a tag that distinguishes between several object shapes. This pattern, called a discriminated union, lets TypeScript narrow the whole object inside a `switch` or `if` just by checking that one literal field.
Discriminated Union
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.side ** 2;
}
}
console.log(area({ kind: "circle", radius: 2 }));const Assertions
By default, TypeScript widens literals declared with `let` or inferred from array/object literals to their general type. Adding `as const` tells the compiler to keep the narrowest possible literal types instead, which is exactly what you want for fixed lists of routes, statuses, or configuration keys.
Deriving a Union from an Array
const routes = ["/home", "/about", "/contact"] as const;
type Route = (typeof routes)[number];
function navigate(route: Route): void {
console.log(`Navigating to ${route}`);
}
navigate("/about");
// navigate("/missing"); // Error: not a valid Route- Discriminated unions for modeling shapes, actions, or states
- Redux/reducer action `type` fields
- CSS-like property values ("solid" | "dashed" | "dotted")
- Configuration keys pulled from a fixed set of environment names
- Template literal types built from string literal unions
Exercise: TypeScript Literal Types
What values does a variable typed as the string literal "red" accept?