Літеральний тип - тип, що допускає одне конкретне значення:
type Method = 'GET' | 'POST' | 'PUT' | 'DELETE';
type Code = 200 | 404 | 500;
function request(method: Method, url: string) {}
request('GET', '/api/users');
request('get', '/api/users'); // помилка: 'get' не входить у Method
Об'єднання літералів - основний спосіб описати скінченний набір значень у TypeScript.
Шаблонні рядкові типи (template literal types) будують рядкові типи за шаблоном - як шаблонні рядки JavaScript, але на рівні типів:
type Size = 'sm' | 'md' | 'lg';
type Color = 'red' | 'blue';
type ClassName = `btn-${Size}-${Color}`;
// 'btn-sm-red' | 'btn-sm-blue' | 'btn-md-red' | ... - усі 6 комбінацій
type EventName = `on${Capitalize<'click' | 'focus'>}`; // 'onClick' | 'onFocus'
type UserRoute = `/users/${number}`;
const ok: UserRoute = '/users/42';
const bad: UserRoute = '/users/abc'; // помилка
Вбудовані типи для рядків: Uppercase, Lowercase, Capitalize, Uncapitalize.
Практичні застосування:
- ключі подій і перекладів:
`auth.${'login' | 'logout'}.title`- помилка в ключі ловиться компілятором; - CSS-значення:
`${number}px` | `${number}%`; - ідентифікатори з префіксом:
`usr_${string}`,`ord_${string}`- різні типи ID не сплутаються; - разом з mapped types - генерація назв методів (
getName,setName) з полів.
Обмеження:
- комбінаторний вибух: кожна позиція множить варіанти. Об'єднання на десятки тисяч рядків уповільнює компілятор, а понад 100 000 членів - помилка «Expression produces a union type that is too complex to represent»;
stringу шаблоні (`usr_${string}`) перевіряє лише форму, а не вміст:usr_з будь-яким продовженням підходить;- лише компіляція: рядки з API чи URL під час виконання не перевіряються - потрібна валідація.