Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як TypeScript розширює виведені літеральні типи (widening) і чому let і const дають різні типи?

Розширення (widening) - TypeScript виводить для змінної ширший тип, ніж конкретне значення, якщо змінна може змінитися.

const a = 'draft';   // тип 'draft' - константа ніколи не зміниться
let b = 'draft';     // тип string - змінна може отримати інше значення

Об'єкти й масиви розширюються навіть у const, бо їх вміст змінюваний:

const post = { status: 'draft' };   // { status: string }
post.status = 'anything';           // дозволено

function publish(status: 'draft' | 'published') {}
publish(post.status);               // помилка: string не 'draft' | 'published'

Способи зберегти вузький тип:

const post = { status: 'draft' as const };                 // { status: 'draft' }
const post2 = { status: 'draft' } as const;                // { readonly status: 'draft' }
const post3: { status: 'draft' | 'published' } = { status: 'draft' };
const post4 = { status: 'draft' } satisfies { status: 'draft' | 'published' };
  • as const - найвужчі літеральні типи й readonly на всіх рівнях;
  • анотація - тип визначає анотація (вона ж і обмежує);
  • satisfies - перевіряє відповідність, але зберігає виведений тип значення.

Контекстна типізація - виведення «ззовні»: якщо тип очікуваного значення відомий, літерал не розширюється:

type Options = { method: 'GET' | 'POST' };
const options: Options = { method: 'GET' };   // ок
fetchJson({ method: 'GET' });                 // ок, якщо параметр типізовано як Options

Також параметри колбеків отримують типи з контексту: items.map((item) => ...).

«Найкращий загальний тип» для масивів - об'єднання типів елементів: [1, 'a'] - (string | number)[], а не кортеж.

Константні параметри типу (TS 5.0) - function f<const T>(x: T) змушує виводити T так, ніби аргумент записано з as const, без вимоги до викликача.

Типова помилка в коді:

const config = { mode: 'production' };   // mode: string
createApp(config);                       // помилка: очікується 'production' | 'development'

Рішення - satisfies AppConfig чи анотація типу при оголошенні, а не as при виклику: as вимикає перевірку значення.

Звуження після перевірок - зворотний процес: let x: string | number, а після typeof x === 'string' у гілці - string.

Докладніше в документації: Виведення типів

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання