Literal Types
Literal Types — типы, значение которых ограничено конкретной литеральной константой:
"red",42,true. TypeScript может использовать конкретное значение как тип, что позволяет создавать точные union-типы и дискриминаторы.
Зачем нужно
Literal types делают API строже и самодокументируемым: вместо string параметр принимает только "left" | "center" | "right". Это исключает опечатки и даёт автодополнение в IDE. В сочетании с discriminated unions — основа паттерна state machine.
Где используется
- Перечисления допустимых строк вместо enum: направления, статусы, роли
- Discriminated unions — поле-дискриминатор (
kind: "circle") as const— фиксация типа объекта/массива как литерала- Перегрузки функций с точными параметрами
- Template literal types — вычисление строковых типов
Основной контент
Строковые литеральные типы
type Direction = "north" | "south" | "east" | "west";
function move(dir: Direction): void {
console.log(`Moving ${dir}`);
}
move("north"); // OK
move("up"); // Error: '"up"' is not assignable to type 'Direction'
Числовые и boolean literal types
type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6;
type Bit = 0 | 1;
function roll(n: DiceRoll): string {
return `Rolled: ${n}`;
}
roll(3); // OK
roll(7); // Error
Widening: let vs const
let a = "hello"; // a: string — let расширяет тип
const b = "hello"; // b: "hello" — const фиксирует литерал
let c: "hello" = "hello"; // явный literal type для let
c = "world"; // Error
as const для объектов и массивов
const config = {
theme: "dark",
lang: "ru",
} as const;
// { readonly theme: "dark"; readonly lang: "ru" }
type Theme = typeof config.theme; // "dark"
const ROLES = ["admin", "user", "guest"] as const;
type Role = typeof ROLES[number]; // "admin" | "user" | "guest"
Перегрузки с literal types
function createElement(tag: "div"): HTMLDivElement;
function createElement(tag: "input"): HTMLInputElement;
function createElement(tag: "span"): HTMLSpanElement;
function createElement(tag: string): HTMLElement {
return document.createElement(tag);
}
const div = createElement("div"); // HTMLDivElement
const input = createElement("input"); // HTMLInputElement
Template Literal Types (TS 4.1+)
type EventName = "click" | "focus" | "blur";
type Handler = `on${Capitalize<EventName>}`;
// "onClick" | "onFocus" | "onBlur"
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
type Endpoint = `/${string}`;
Частые ошибки
let-переменная в literal-позиции —let x = "left"имеет типstring; нужноas constили явный типlet x: "left" = "left".type T = "a" | "b" | string—stringпоглощает литералы, union схлопывается доstring.- Забыть
as constдля объектных констант — без него TypeScript расширяет поля доstring,number. - Использовать enum когда достаточно literal union —
as constобъект +typeof ROLES[number]часто читаемее.