A Type That's One Specific Value
Literal Types
Literal types restrict a value to one specific string, number, or boolean. Combined with unions, they're how TS models "one of these options".
What you'll learn
- Use literal string / number / boolean types
- Combine with unions
- Use `as const` to lock down inferred types
A literal type is a type whose only value is one specific
value. "admin" is a type; 42 is a type; true is a type.
String Literals
let role: "admin" = "admin";
role = "user";
// ~~~~~~ Type '"user"' is not assignable to type '"admin"'. By itself, a single literal type is rarely useful. Combine with unions:
type Role = "admin" | "user" | "guest";
function check(r: Role) {
if (r === "admin") { /* ... */ }
}
check("admin"); // ✓
check("hacker"); // ✗ Argument of type '"hacker"' is not assignable... A union of literal types is “one of these specific values”. The go-to for variant fields.
Number and Boolean Literals
type Bit = 0 | 1;
type Direction = -1 | 0 | 1;
type Strict = true; // useless alone, but valid How TS Decides Wide vs Narrow
let kind = "admin"; // string
const kind = "admin"; // "admin"
let kind: "admin" = "admin"; // "admin" — explicit let widens (you might reassign); const keeps the literal type
(you can’t change it).
Object Field Widening
By default, object literals widen string fields:
const config = { mode: "dev" };
// ^ { mode: string } — NOT { mode: "dev" } To keep the literal type, use as const:
const config = { mode: "dev" } as const;
// ^ { readonly mode: "dev" } as const recursively makes everything readonly AND keeps
literal types narrow. Useful for configuration objects and
“enum-like” data.
Pattern — Discriminator Field
type Event =
| { type: "click"; x: number; y: number }
| { type: "key"; key: string }; The type field’s value is a literal type per branch. Switching on
event.type narrows the rest of the object — the foundation of
discriminated unions.
Up Next
Optional and readonly properties.
Optional & Readonly →