ООО «Ивент Хаб» · Москва · работаем по всей России
Пн—Пт, 10:00—19:00hello@gusi-lebedi.comРеквизиты
Практическое руководство

TypeScript: как типизация помогает веб-проекту и чего она не проверяет

Как находить несогласованности в коде до запуска и почему описанный тип не проверяет настоящий ответ API. Разбираем возможности TypeScript и переход существующего веб-проекта.

Типизация данных и развитие веб-проекта с TypeScript

В карточке заказа всё выглядит правильно, пока один из сервисов не присылает сумму строкой, а другой компонент не ищет поле с прежним названием. Разработчик замечает проблему уже в работающем интерфейсе. Часть подобных несогласованностей можно обнаружить раньше, пока код ещё не выполняется. Для этого в JavaScript-проектах используют TypeScript.

В Гуси-Лебеди мы предлагаем разбирать эту технологию через данные и действия приложения. Что именно считается заказом? Какие значения принимает его статус? Может ли отсутствовать телефон покупателя? Ответы помогают команде согласовать модель, а проверка типов показывает, где код этой модели противоречит.

TypeScript добавляет к JavaScript систему типов и статическую проверку. Основные принципы описаны в официальном руководстве TypeScript. Это не отдельный движок для браузера и не замена тестированию сайта. В обычной сборке из кода получают JavaScript, а сведения о типах удаляются. Поэтому важно различать два вопроса: согласованы ли части программы между собой и действительно ли поступившие данные соответствуют ожиданиям.

Как типы помогают описывать данные и функции

Описание типов данных и входов функции

Представим условный интернет-магазин. В модели заказа есть идентификатор, сумма и статус. Идентификатор хранится строкой, сумма числом, а статус принимает только согласованные значения: например, «новый», «оплачен» или «отменён». Это учебная модель, а не описание выполненного проекта.

Зачем ограничивать статус? Если оставить произвольную строку, написание «оплчен» тоже окажется строкой. Для набора разрешённых значений можно описать объединение строковых литералов. Тогда при использовании неправильного значения в проверяемом коде TypeScript сможет сообщить о несоответствии. Он проверяет модель, которую задала команда; правильность самих бизнес-правил всё равно нужно обсуждать.

С функциями действует тот же принцип. Функция расчёта получает значения определённых типов и возвращает результат. Если ей передать объект вместо ожидаемого числа, проверка может обнаружить ошибку в месте вызова. Разработчику не приходится искать её только по результату на экране.

Типы не обязательно писать возле каждой переменной. TypeScript умеет выводить их из значения и контекста. Если переменная получила строку, явная повторная запись типа часто не требуется. Внешние границы и важные модели, напротив, полезно описывать так, чтобы другим участникам команды было понятно, что функция принимает и возвращает.

Необязательное поле тоже нужно обсуждать явно. Отсутствующий телефон не является ни пустой строкой, ни гарантированным номером. Код, который без проверки обращается к такому значению, может привести к ошибке. Строгость обнаружения подобных случаев зависит от настроек проекта, поэтому расширение .ts само по себе ничего не доказывает.

Практическая ценность типов особенно заметна при изменениях. Команда переименовала поле или добавила новое состояние заказа. Проверка помогает найти места, ожидания которых больше не совпадают с новой моделью. Но она не решит, правильную ли скидку выбрали, дошло ли уведомление и можно ли конкретному сотруднику отменять заказ.

Где заканчивается статическая проверка

Статическая модель и отдельная проверка входящих данных

Описание ответа API существует в коде, а настоящий ответ приходит позже, во время работы приложения. Сервер может вернуть пустое поле, другую структуру или сообщение об ошибке. Объявление ожидаемого типа не преобразует ответ и не доказывает его содержимое.

Поэтому на границе интеграции нужна отдельная проверка поступивших данных: формы, файла, ответа внешнего сервиса. После неё приложение решает, может ли продолжать работу или должно показать понятную ошибку. Статическая типизация помогает использовать уже проверенные значения согласованно, но не заменяет эту границу.

В нашем примере внешняя система прислала сумму строкой. Запись «считать ответ заказом» не сделает эту строку числом. Нужно решить, разрешён ли такой формат, как его преобразовать и что делать при недопустимом значении. Требования к этому обмену стоит закрепить в контракте запросов и ответов REST API.

У TypeScript есть способы ослабить проверку. Тип any позволяет выполнять операции без обычного контроля типа этого значения. Он бывает нужен на переходном участке, но если им описано почти всё приложение, ожидать полноценного обнаружения несогласованностей нельзя. Важно смотреть, где именно осталось такое исключение и почему.

Тип unknown отражает другое решение: значение поступило, но его устройство пока не подтверждено. Прежде чем обращаться с ним как с заказом, код должен уточнить тип. Само слово unknown ещё не проверяет бизнес-правила. Однако оно не позволяет беспрепятственно обращаться к произвольным полям, как это допускает any.

Утверждение типа через as не является проверкой данных. Оно сообщает проверяющей системе, какое представление использовать, и исчезает при компиляции. Если реальное значение другое, никакого автоматического исправления не произойдёт. Именно поэтому зелёный результат проверки после нескольких утверждений типа нужно оценивать вместе с кодом, а не отдельно от него.

Сумма может быть числом, но вычисляться по неправильному правилу. Заказ может соответствовать описанной структуре, но принадлежать другому покупателю. Проверка типов не заменяет проверку расчётов и прав доступа. Эти случаи проверяют собственными сценариями.

Как готовить переход существующего проекта

Постепенный переход к описанным типам в проекте

Перевод на TypeScript не обязательно начинать с переписывания всего сайта. В существующем проекте сначала выясняют, как собирается приложение, какие файлы используются и какие библиотеки зависят друг от друга. Полезен небольшой участок, где можно проследить данные от входа до результата: например, модуль отображения заказа. Это пример выбора, а не универсальное требование.

Сначала сборка и исходники. Команда определяет, где находится исходный код, куда попадают выходные файлы и каким инструментом создаётся рабочая версия. Выход сборки не должен случайно перезаписывать исходники. В официальном руководстве по миграции с JavaScript это рассматривается до перевода отдельных файлов.

Затем совместная работа JS и TS. Настройка allowJs позволяет включать JavaScript-файлы в проект TypeScript. Настройка checkJs включает сообщение об ошибках в таких файлах. Это разные действия: возможность включить файл ещё не означает, что он проверяется с ожидаемой строгостью. Для постепенного перехода полезно заранее выбрать и зафиксировать режим.

После этого модель и зависимости. У выбранного участка описывают входы, результаты и состояния. Проверяют доступные описания типов библиотек и соответствие их используемым версиям. Если внешние данные остаются непроверенными, этот пробел не нужно скрывать переименованием файла из .js в .ts.

Наконец, правила выпуска. Команда решает, какая команда выполняет проверку типов и что останавливает публикацию новой версии. Полученный JavaScript не всегда доказывает отсутствие ошибок типизации: например, поведение выдачи файлов связано с настройкой noEmitOnError, а конкретный инструмент сборки может выполнять только преобразование синтаксиса. Поэтому в процессе выпуска нужен наблюдаемый результат именно проверки типов.

Не стоит гасить все сообщения добавлением any или as, чтобы быстрее получить зелёную отметку. Иногда исключение обосновано, но его место и причина должны быть понятны. Ошибка в модели и нехватка описания библиотеки требуют разных решений.

После изменения повторяют пользовательские сценарии выбранного участка. В магазине это загрузка заказа, отсутствующие данные, ошибка API и доступные действия. TypeScript сохраняет обычное поведение JavaScript, но изменения, которые команда внесла при переходе, всё равно могут повлиять на приложение.

Такой переход можно включить в развитие веб-сервиса, если он решает конкретную задачу проекта. Когда проблема состоит в непонятных бизнес-правилах или нестабильной внешней системе, одних описаний типов недостаточно. Срок и стоимость миграции оценивают после разбора кода, зависимостей и требуемого охвата.

Как принимать типизацию и поддерживать её дальше

Приёмка статической проверки и поведения приложения

Заказчику не нужно изучать каждый тип, чтобы задать полезные вопросы исполнителю. Достаточно различать четыре результата: модель данных описана, проверка действительно выполняется, приложение собирается и пользовательские сценарии работают. Отчёт по одному из них не подтверждает остальные.

При приёмке попросите показать выбранный участок и объяснить, какую проблему решает типизация. Если изменилось название поля заказа, где проверка покажет несовпадение? Если API прислал неожиданный ответ, где он отклоняется? Если роли пользователя изменились, какая часть системы проверяет доступ? Вопросы помогают увидеть границы решения без демонстрации красивой диаграммы вместо работающего процесса.

В протоколе полезно сохранить:

  • Версию приложения, настройки и фактическую команду проверки типов.
  • Участки, которые вошли в переход, и оставшиеся исключения.
  • Результат проверки, сборки и существенных пользовательских сценариев.
  • Ответственного за обновление модели при изменении API и требований.

Это предлагаемый состав проверки, а не утверждение, что мы уже испытали конкретный проект. Для чужой системы нужны её реальные результаты.

Дальше типы становятся частью обычной разработки. Добавили новое состояние заказа, пересмотрели модель и обработку этого состояния. Изменили внешний ответ, обновили договорённость об обмене, проверку данных и описания. Обновили библиотеку, проверили совместимость её типов с приложением. В сопровождении сайта с TypeScript важно сохранять эту связь, чтобы модель не отставала от продукта.

Для Гуси-Лебеди смысл TypeScript состоит в более ясных договорённостях внутри кода и возможности раньше заметить определённые ошибки. Он особенно полезен там, где данные проходят через несколько компонентов и регулярно меняются. Решение о внедрении стоит принимать по устройству проекта и задачам команды, а результат оценивать по охвату проверки и поведению приложения.

Начать проект

Обсудим вашу задачу

Ответим в течение рабочего дня. Можно без технического задания — достаточно цели и вводных.

Заполнить короткий бриф ↗
Навигация по экспертизе

Ещё направления для вашего проекта

Все 86 услуг →