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" | stringstring поглощает литералы, union схлопывается до string.
  • Забыть as const для объектных констант — без него TypeScript расширяет поля до string, number.
  • Использовать enum когда достаточно literal unionas const объект + typeof ROLES[number] часто читаемее.

Связанные темы

Ресурсы