Что дают noUncheckedIndexedAccess, exactOptionalPropertyTypes и strict-режим в tsconfig?
strict включает базовый набор проверок; noUncheckedIndexedAccess добавляет | undefined при индексном доступе к массивам и Record; exactOptionalPropertyTypes запрещает явный undefined там, где свойство просто необязательно.
strict-режим в tsconfig
Флаг "strict": true включает сразу несколько проверок одним ключом: strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitAny, noImplicitThis, alwaysStrict и useUnknownInCatchVariables. Это базовая линия безопасности для любого нового проекта.
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true
}
}
noUncheckedIndexedAccess
Без этого флага TypeScript считает, что обращение к массиву или Record по индексу всегда возвращает элемент нужного типа. Это неверно — индекс может выйти за границы.
const arr: string[] = ['hello'];
// Без noUncheckedIndexedAccess:
const s: string = arr[99]; // компилятор молчит, runtime — undefined
// С noUncheckedIndexedAccess:
const s2 = arr[99]; // тип: string | undefined
const len = s2.length; // Ошибка: Object is possibly 'undefined'
const len2 = s2?.length; // OK
Аналогично для Record<string, T>:
const map: Record<string, number> = {};
const val = map['missing']; // number | undefined — безопаснее
exactOptionalPropertyTypes
По умолчанию TypeScript разрешает явно присвоить undefined необязательному свойству, хотя семантически это разные вещи: свойство «отсутствует» vs свойство «присутствует со значением undefined».
interface Config {
timeout?: number; // означает: число ИЛИ свойство не существует
}
// Без exactOptionalPropertyTypes — оба варианта OK:
const c1: Config = { timeout: undefined }; // присвоено undefined
const c2: Config = {}; // свойство отсутствует
// С exactOptionalPropertyTypes:
const c3: Config = { timeout: undefined }; // Ошибка!
// Type 'undefined' is not assignable to type 'number'
const c4: Config = {}; // OK
// Чтобы разрешить undefined явно — укажите union:
interface Config2 {
timeout?: number | undefined;
}
Это критично при работе с Object.assign, spread и Partial<T> — без флага можно случайно «затереть» существующее свойство через явный undefined.
Сравнение и когда включать
strict— включать всегда на новых проектах.noUncheckedIndexedAccess— включать если важна корректность работы с коллекциями; на легаси-коде может дать много предупреждений сразу.exactOptionalPropertyTypes— включать если код активно использует необязательные свойства и важно различать «нет свойства» и «свойство = undefined»; хорошо сочетается с Zod/Valibot-схемами.
Подводные камни
- noUncheckedIndexedAccess ломает for-of безопасным способом — итерация через индекс (
arr[i]) потребует проверки, хотя for-of сам по себе гарантирует существование элемента. - Partial<T> + exactOptionalPropertyTypes —
Partial<T>генерируетprop?: T[K]без| undefined, что означает: явноеundefinedснова запрещено в Partial-объектах. - Миграция существующей кодовой базы — включение этих флагов на большом проекте может выдать сотни ошибок одновременно; лучше включать постепенно через
@ts-expect-error. - Взаимодействие с библиотеками — типы из
@types/*не всегда написаны с учётом exactOptionalPropertyTypes и могут конфликтовать. - noUncheckedIndexedAccess не охватывает деструктуризацию —
const [first] = arrне добавляет| undefinedк first, только прямой индекс. - Ложная строгость с tuples — для tuple типов TypeScript знает длину, но noUncheckedIndexedAccess всё равно добавляет
| undefinedпри доступе через переменный индекс. - strict не включает noUncheckedIndexedAccess и exactOptionalPropertyTypes — это отдельные флаги, которые нужно добавлять явно даже при
"strict": true.
Common mistakes
- Отвечать определением без production-сценария.
- Не называть runtime boundary, security boundary или failure mode.
- Игнорировать версию API, observability и тестовую проверку.
What the interviewer is testing
- Объясняет механизм своими словами и без выдуманных API.
- Называет реальные риски, диагностику и критерий корректности.
- Связывает ответ с текущей документацией и миграционными ограничениями.