TypeScript для тех кто устал от неожиданных undefined

Если вы когда-либо просыпались в три часа ночи от уведомления в Sentry о том, что ваш продакшн «упал» из-за ошибки TypeError: Cannot read property 'id' of undefined, то эта статья для вас.
Для многих JavaScript — это прекрасный, гибкий, но абсолютно непредсказуемый инструмент. Мы привыкли к тому, что переменная может быть числом, строкой, объектом, а в самый неподходящий момент — превратиться в undefined или null, обрушив всё приложение. В индустрии это называют «динамической типизацией», но на практике это часто ощущается как игра в рулетку.
TypeScript пришел не для того, чтобы усложнить нам жизнь лишним синтаксисом. Он пришел, чтобы перенести поиск ошибок с этапа «пользователь нажал кнопку» на этап «я нажал Ctrl+S».
Почему JavaScript нас предает?
Проблема JS в том, что он слишком всепрощающий. Вы можете передать в функцию строку вместо массива, забыть вернуть значение из метода или попытаться обратиться к полю объекта, который еще не успел загрузиться из API. Интерпретатор не скажет вам об этом до тех пор, пока код не будет выполнен.
В больших проектах, где над кодом работают 5–10 человек, эта проблема масштабируется экспоненциально. Вы меняете структуру объекта в одном модуле, а в другом — в каком-нибудь забытом компоненте на 14-й странице — всё ломается, потому что там кто-то полагался на старую структуру.
TypeScript как страховой полис
TypeScript — это не новый язык, а «надстройка» (суперсет) над JavaScript. Его главная задача — добавить статическую типизацию. Это значит, что мы описываем форму наших данных заранее.
Когда вы четко говорите: «Здесь будет объект с полем username типа string», IDE начинает работать на вас. Как только вы попытаетесь обратиться к user.name вместо user.username, редактор подсветит это красным. Вам не нужно запускать код и ждать ошибки в консоли — вы видите проблему в момент написания.
Борьба с undefined: главный арсенал
Самая большая ценность TS — это не просто указание типов string или number. Настоящая магия начинается там, где мы управляем отсутствием данных.
1. Strict Null Checks: Режим «Без пощады»
Первое, что нужно сделать любому, кто переходит на TypeScript — включить опцию strictNullChecks в tsconfig.json. Без неё TS позволяет присваивать null или undefined любой переменной. С ней — нет.
Теперь, если вы объявили переменную как User, она обязана быть пользователем. Если она может отсутствовать, вы обязаны явно указать это: User | undefined. Это заставляет вас думать о крайних случаях еще до того, как вы написали бизнес-логику.
2. Union Types и защита типов (Type Guarding)
Когда мы помечаем тип как User | undefined, TypeScript больше не позволит нам просто так вызвать user.getName(). Он скажет: «Стоп, а что если здесь undefined?».
Чтобы «успокоить» компилятор, мы используем механизмы защиты:
- Простая проверка на истинность:
if (user) { ... }— самый простой способ. - Optional Chaining (Опциональная цепочка): Оператор
?.позволяет безопасно обращаться к вложенным свойствам. Вместо огромных цепочек проверокif (user && user.address && user.address.city), мы пишемuser?.address?.city. Если любой элемент в цепочке окажетсяnullилиundefined, выражение просто вернетundefined, не обрушив приложение. - Nullish Coalescing (Оператор нулевого слияния): Оператор
??позволяет задать значение по умолчанию. Например:const name = user?.name ?? 'Аноним'. Это гораздо надежнее, чем старый добрый||, который мог заменить на «Анонима» даже пустое число0или пустую строку, что часто приводило к другим багам.
Как правильно проектировать типы, чтобы не сойти с ума
Многие новички совершают ошибку, пытаясь типизировать абсолютно всё с избыточной строгостью или, наоборот, используя везде тип any.
any — это «черный ход», который отключает проверку типов. Использование any превращает TypeScript обратно в JavaScript. Если вы пишете any, вы говорите компилятору: «Я не знаю, что здесь, и мне всё равно». Это прямой путь к тем самым undefined, от которых мы бежим.
Правильный подход к типизации:
- Используйте Интерфейсы (
interface) для структур данных. Опишите API-ответы, модели пользователей, настройки приложения. Это создает «контракт», который соблюдают все части системы. - Используйте Типы (
type) для объединений и алиасов. Например, статус заказа:type OrderStatus = 'pending' | 'shipped' | 'delivered'. Теперь вы не сможете передать туда строку'sent', потому что её нет в списке допустимых значений. - Избегайте принудительного приведения типов (
as User). Операторas— это способ сказать: «Верь мне, я знаю, что здесь User». Но TS вам верит на слово, а в рантайме там может оказаться что угодно. По возможности используйте Type Guards (функции-проверки).
Практический профит: что меняется в процессах
Переход на TS меняет не только код, но и то, как вы работаете с командой:
- Самодокументированный код. Вам больше не нужно писать в комментариях
/** @param {Object} user - User object with id and name */. Типuser: Userговорит об этом лучше любого комментария. - Безопасный рефакторинг. Хотите переименовать поле
userIdвidво всем проекте? В JS это было бы поиском и заменой по всему проекту с молитвой о том, что вы ничего не пропустили. В TS вы переименовываете поле в интерфейсе, и IDE автоматически меняет его везде, либо подсвечивает все места, где теперь возникла ошибка. - Ускорение онбординга. Новый разработчик в команде просто открывает определение типа и сразу видит, какие данные приходят из API и какие методы доступны у объекта. Ему не нужно «прокликивать» весь путь выполнения кода, чтобы понять структуру данных.
Заключение: стоит ли оно того?
Да, порог входа выше. Да, сначала вы будете ругаться на компилятор, который «не дает вам просто написать код». Но этот дискомфорт — это цена, которую вы платите за спокойный сон.
TypeScript не делает вас идеальным программистом, но он работает как опытный коллега, который стоит за плечом и тихо говорит: «Слушай, а ты уверен, что здесь точно будет объект? А если API вернет ошибку?».
В итоге количество runtime-ошибок сокращается в разы, а уверенность в каждом коммите растет. Переход на TS — это переход от культуры «надеюсь, оно заработает» к культуре «я знаю, что оно работает». Если вы устали от неопределенности и хаоса в типах — самое время перестать бороться с undefined вручную и доверить эту работу инструментам.

