Данные в React-приложениях передаются по однонаправленному потоку: через пропсы (или React Context) от родительских компонентов к дочерним и через колбэки от дочерних к родительским. Типизация пронизывает этот поток, помогая разработчику документировать данные на разных слоях, обнаруживать ошибки на стадии написания кода и проектировать упрощённую логику.  При изменении логики на одном уровне приложения возможно появление ошибок в зависимом коде, которые анализатор TypeScript подсвечивает. Разработчику остаётся переписать типизацию и логику. Чтобы каждый раз не обслуживать зависимые типы, их можно конструировать на основе базовых, таким образом связывая типы. 1. Как типизировать данные2. Как понимать типы3. Как использовать типизацию4. Глубокая типизация5. Связанная типизация6. Изящная типизация Связанность типов была продемонстрирована в прошлой статье на примере связи типа пропсов иконок и имен файлов, содержащих иконки. Большую часть проблем в случае изменения логики покрывает глубокая типизация. Связанная типизация демонстрирует в структуре типов, откуда данные приобретают свой тип, а также уменьшает повторяющийся код в контексте типов. Рассмотрим обобщённый вид потока данных и их трансформацию в приложении React, использующее в качестве state-менеджера Redux. Каждый слой в приложении выполняет свою задачу. Точки трансформации данных могут располагаться в других местах или вовсе отсутствовать. Это зависит от целесообразности и договорённостей на проекте.  Например, бэкэнд может присылать уже удобные данные, а преобразование данных для хранилища может происходить в редьюсере, а не миддлваре. Хочется заметить, что бэковая и фронтовая части приложения - это две разных истории формирования данных. Бэкэнд-разработчики привязывают имена переменных и модели к сервисам и базе данных, фронтэнд-разработчики ориентируются на то, что видит пользователь. Поэтому пытаться прогнуть контракт под законы своего кода, немного неправильно. Куда важнее подготовить фронтовое приложение к казусам несоответствия имён бэка и фронта, чтобы в случае чего с лёгкостью трансформировать нежелательные имена через готовое решение. Мы можем увидеть, что данные, пришедшие на фронт и отправляемые на бэк, каким-то образом связаны. Для того, чтобы TypeScript контролировал эту связь, нужно связывать типизацию разных слоёв. К примеру, данные с бэкэнда очень похожи на то, что мы хотим сохранить в хранилище. Тогда нужно создать тип, описывающий данные в store, на основе типа, описывающего модель данных с бэка: Код 5.1. Привязывание типа StoreData к типу BackendData с преобразованием поля profile_id Для лучшего понимания кода были созданы промежуточные типы Id и BackendDataWithoutId, хотя можно обойтись и без них: Если в процессе создания новых фич в приложении, разработчики выясняют, что поле profile_id может иметь значение null, то достаточно будет это прописать в типе BackendData, связанные с ним типы автоматически подхватят новый тип и анализатор подсветит проблемы в логике на нижних слоях. Точно так же мы могли бы описывать пропсы компонента, привязывая их типы к типу хранилища: Код 5.2. Привязывание типа Props к типам отдельных полей StoreData Помимо того, что нам не требуется повторяться в коде, в очередной раз используя описанные типы, мы явно демонстрируем откуда эти типы происходят, что очень удобно в понимании общей структуры данных в приложении. Таким образом через типы связываются все данные в приложении (если они связаны логикой).  В TypeScript многие операторы и конструкции используют базовый тип для построения нового: keyof получает ключи из базового типа, удобен, когда нужно ориентироваться на ключи какого-то типа, вместо дублирования строк; typeof определяет тип константы, как её видит анализатор, удобен вместо явного прописывания типа существующим в коде константным значениям; mapped типы (с использованием оператора in) позволяет создавать объектные типы, используя ключи и их типы базового. Pick, Omit, Partial и другие основаны на mapped типах и удобны для изменения исходного объектного типа. Предпочтительно использовать связывание типов с их помощью, нежели переписывать новые типы, уменьшая гибкость типизации приложения. Следующая статья: TypeScript в React-приложениях. 6. Изящная типизация