Ты поймёшь, что на самом деле включает строгий режим, и научишься разбираться с типичными ошибками, которые он вскрывает в существующем проекте.
Открыть этот урок в Kodokon"strict": true - это не одна опция, а агрегат, который включает целое семейство проверок: strictNullChecks, noImplicitAny, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitThis, useUnknownInCatchVariables и alwaysStrict. Каждая новая версия TypeScript может добавить сюда новые: включая strict, ты подписываешься и на будущие проверки. При этом любой флаг можно отключить по отдельности, что позволяет мигрировать существующую кодовую базу постепенно.
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"noFallthroughCasesInSwitch": true,
"exactOptionalPropertyTypes": true,
"verbatimModuleSyntax": true,
"skipLibCheck": true
}
}Два самых влиятельных флага - strictNullChecks и noImplicitAny. Первый убирает null и undefined из всех типов: каждое потенциально отсутствующее значение нужно объявить как T | undefined и обработать до использования. Второй запрещает неаннотированному параметру молча стать any. Вместе они устраняют два больших семейства багов JavaScript: "cannot read property of undefined" и распространение непроверенных значений. useUnknownInCatchVariables дополняет картину: переменная в catch имеет тип unknown, ведь в JavaScript можно бросить что угодно.
function findPort(
env: Record<string, string | undefined>
): number {
const raw = env["PORT"];
if (raw === undefined) {
return 3000;
}
return Number.parseInt(raw, 10);
}
declare function riskyOperation(): void;
try {
riskyOperation();
} catch (err) {
const message =
err instanceof Error ? err.message : String(err);
console.error(message);
}Частые ошибки миграции и их настоящие лекарства. "Object is possibly undefined": вместо утверждения non-null !, которое лишь переносит падение в другое место, предпочитай сужение (if), опциональную цепочку ?. или значение по умолчанию через ??. "Property has no initializer" (strictPropertyInitialization): инициализируй в конструкторе, а не вешай ! на поле. Ещё берегись ловушки ?? против ||: port || 3000 заменяет также 0 и "", тогда как port ?? 3000 заменяет только null и undefined.
interface Settings { retries?: number }
function resolveRetries(s: Settings): number {
const bad = s.retries || 3;
const good = s.retries ?? 3;
return good;
}
const names = ["Ada", "Linus"];
const first = names[0];
const upper = first?.toUpperCase() ?? "N/A";Помимо агрегата, три опции стоит обсудить командой. noUncheckedIndexedAccess добавляет undefined к каждому доступу по индексу (arr[i], dict[key]): безопаснее, но многословно в коде, где много работы с массивами, - многие команды включают её только на новых проектах. exactOptionalPropertyTypes различает "свойство отсутствует" и "свойству присвоен undefined", что критично для патчей. skipLibCheck пропускает проверку файлов .d.ts твоих зависимостей: осознанный компромисс между временем сборки и обнаружением конфликтов между библиотеками.
"strict": true в tsconfig.json?retries?: number равен 0, в чём разница между retries || 3 и retries ?? 3?// @ts-expect-error, чем // @ts-ignore?