Angular IDPStrong Junior
🔥 0

Модуль 2 · урок 10 з 15

Strict TypeScript

Тут починається друга половина модуля — TypeScript. Вимога ліда звучить жорстко: strict-режим і рівно нуль any. Це не про суворість заради суворості: strict змушує відповісти на питання «а що, як тут порожньо?» під час написання коду, а не в проді.

Що вмикає strict

Один прапорець "strict": true — це група перевірок. Найважливіші три:

ПеревіркаЩо ловить
strictNullChecksnull і undefined більше не входять у кожен тип — їх треба вказати явно й обробити
noImplicitAnyПараметр без типу, який TypeScript не зміг вивести, стає помилкою, а не мовчазним any
strictFunctionTypesНесумісні сигнатури колбеків
strictPropertyInitializationПоле класу, яке ніколи не отримає значення

strictNullChecks на прикладі

// без strict: типи брешуть
function greet(user: User) {
  return 'Привіт, ' + user.name;   // впаде, якщо прийде null — але компілятор мовчить
}

// зі strict: тип чесний
function greet(user: User | null) {
  if (!user) return 'Привіт, гостю';   // компілятор ЗМУСИТЬ це написати
  return 'Привіт, ' + user.name;       // тут TS уже знає, що user не null
}

Останній рядок — це звуження типу: після перевірки TypeScript сам розуміє, що всередині user точно є. Ніяких зайвих перевірок писати не треба.

Інструменти для роботи з порожнечею

user?.address?.city              // undefined замість помилки
user.getName?.()                 // виклик, лише якщо метод існує
list?.[0]                        // безпечний доступ до елемента

const name = user.name ?? 'Гість';   // підставити, лише якщо null або undefined
const name = user.name || 'Гість';   // ⚠️ спрацює ще й на '' та 0

// раннє повернення читається краще, ніж вкладені if
function total(order: Order | null): number {
  if (!order) return 0;
  if (!order.items.length) return 0;
  return order.items.reduce((s, i) => s + i.price, 0);
}

Знак оклику: коли можна, а коли це борг

const el = document.querySelector('.btn')!;   // «я гарантую, що не null»

! вимикає перевірку в одному місці. Інколи це чесно — наприклад, ти щойно сам створив цей елемент. Але частіше це спосіб замовчати проблему: якщо гарантія виявиться хибною, впаде рантайм, а компілятор уже нічого не скаже.

// краще так: обробити відсутність явно
const el = document.querySelector<HTMLButtonElement>('.btn');
if (!el) return;
Виняток, який ти писатимеш законно

@Input() task!: Task; — тут ! означає «значення прийде ззовні, до першого рендеру Angular його підставить». Це домовленість фреймворку, а не приховування проблеми. У сигнальному стилі вона зникає сама: input.required<Task>() гарантує наявність на рівні типів, і знак оклику не потрібен.

strictTemplates: перевірка типів у шаблонах

@Component({
  template: `<app-task-card [task]="taskId()" />`,   // ❌ передали string, а чекають Task
})

Без strictTemplates шаблон — сліпа зона: помилка виявиться в рантаймі як undefined is not an object. З ним — це помилка компіляції з нормальним поясненням. Прапорець уже стоїть у нових проєктах; головне не вимкнути його, коли щось «не збирається».

Кілька додаткових прапорців, які варто ввімкнути

{
  "compilerOptions": {
    "noUnusedLocals": true,        // невикористані змінні — помилка
    "noImplicitReturns": true,     // функція має повертати значення на всіх шляхах
    "noFallthroughCasesInSwitch": true,
    "exactOptionalPropertyTypes": true   // відрізняє «поля немає» від «поле = undefined»
  }
}
Правильні реакції на помилку типів
  • Уточнити тип: User | null замість User.
  • Додати перевірку й ранній вихід.
  • Змінити модель так, щоб неможливий стан не виражався типом.
  • Написати type guard (наступні уроки).
Спроби замовчати
  • as any — валить збірку через ESLint.
  • ! без реальної гарантії.
  • // @ts-ignore — те саме, тільки гірше видно.
  • Вимкнути strict «поки що».
Що це дає на практиці

Приблизно половина рантайм-помилок у фронтенді — це «читаю поле в чогось, чого немає». Strict перетворює цей клас помилок на помилки компіляції. Тобто ти платиш кількома хвилинами роздумів під час написання коду й не платиш годиною дебагу в проді.

≈ 45 хв · +25 XP за урок