Расширьте возможности разработчиков с помощью динамических типов

Всем привет! Этот пост основан на последнем выступлении Жана Себастьяна на Strapi Conf 2023. Ссылку на видео дам в конце поста.

JS — бэкэнд-инженер, специализирующийся на опыте разработчиков в Strapi. Он также любит TypeScript.

Убери это, Джейс.

Всем привет! Меня зовут Жан Себастьян, и я рад поделиться некоторыми мыслями о том, как вы можете улучшить свой опыт разработчика, особенно при работе с приложениями с высокодинамичными структурами контента с использованием TypeScript. Итак, без лишних слов, давайте копать.

Почему TypeScript?

TypeScript — это мощный инструмент, расширяющий возможности разработчиков благодаря многочисленным функциям. К ним относятся, помимо прочего, функции, обеспечивающие безопасность типов, предлагающие улучшенный IntelliSense и упрощающие навигацию по сложным базам кода.

Например,

  • Безопасность типов: TypeScript помогает в раннем выявлении ошибок с помощью проверок во время компиляции и анализа в реальном времени в интегрированных средах разработки (IDE).
  • Исследование кодовой базы: функции аннотации типов и перехода к объявлению невероятно полезны для удобочитаемости и отслеживаемости кода.
  • IntelliSense: TypeScript выводит кодирование на новый уровень, предлагая руководство в реальном времени, начиная от автоматического завершения и заканчивая предложением кода.

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

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

Однако если предположить, что TypeScript — это волшебная палочка, преобразование JavaScript в TypeScript с помощью простой операции переименования было бы наивным.

TypeScript великолепен… в большинстве случаев.

TypeScript очень хорошо работает с intellisense или проверкой типов, потому что он опирается на источник истины, типы, определенные разработчиками.

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

Машинопись является только рефери; он читает правила, написанные разработчиками.

Здесь, в Страпи, у нас есть интересный вызов. Мы не знаем структуру контента заранее или что-то точное о нашей модели пользовательских приложений.

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

Создание общих типов — непростая задача. Как будет работать TypeScript, когда модели крайне непредсказуемы?

Во-первых, давайте рассмотрим пример получения данных. Цель состоит в том, чтобы создать универсальную функцию, которая запрашивает данную модель, чтобы получить связанный с ней контент из базы данных.

Хотя приведенный выше код является точным с точки зрения Typescript, он не очень помогает нам при разработке нашего приложения, потому что здесь у нас есть свободная проверка типов, нет автозаполнения для доступных uid или какой-либо информации о значениях, которые мы можем ожидать в ответ.

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

Чтобы исправить это, нам потребуется доступ к какой-то базе данных машинописи или реестру всех моделей, которые существуют в нашем внешнем приложении, и их uid.

Мы можем изменить наш код на следующий.

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

Реестры динамических типов

Реестры динамического типа — это обычные интерфейсы, объявленные в общем модуле, которые будет экспортировать магазин Strapi.

Хотя по умолчанию он пуст, мы решили использовать возможности слияния и расширения интерфейсов, чтобы позволить вашему приложению или плагину Strapi добавлять новые определения типов в эти интерфейсы.

Например, если вы используете модель статьи в своем приложении Strapi, вы можете зарегистрировать ее в общем интерфейсе, чтобы Strapi могла использовать ее при использовании внутреннего API.

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

В конце концов, это позволяет нам писать универсальные API-интерфейсы на основе абстрактных моделей и сущностей на стороне Strapi, предоставляя при этом всю мощь автозаполнения машинописного текста и IntelliSense в пользовательских проектах, расширяющих реестры типов.

Вот схема того, что мы только что объяснили; как видите, Strapi предоставляет модуль общих реестров, содержащий множество интерфейсов.

Затем модуль и его интерфейсы расширяются внешними субъектами, такими как приложение или плагин, и затем могут использоваться кем угодно для создания пользовательских APS или просто ссылочных типов.

Хотя это решает проблему наличия точных типов и разработки мощных типизированных API, это не очень масштабируемое решение.

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

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

Автоматическая генерация типа.

Он состоит в том, что Strapi считывает ваши модели приложений для создания типов, которые затем дополняют динамические реестры.

Но сначала определимся с нашими потребностями.

  1. Это нужно сделать программно.
  2. Необходимо создавать типы с литеральными значениями.
  3. Он должен быть ремонтопригодным.

И следует избегать манипуляций со строками, таких как конкатенация и т. д., которые привели нас к открытию TypeScript Factory API.

Фабричный API TypesScript

Фабричный API TypeScript — это набор утилит, предназначенных для создания узлов TypeScript AST и управления ими. Затем узлы можно использовать для создания определений в исходном файле.

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

Здесь вы можете увидеть, что происходит, когда мы вручную запускаем генерацию типов, поскольку она создает типы для типов контента и компонентов приложения Strapi.

И здесь мы можем видеть часть того, что излучается.

Мы можем наблюдать расширение модуля хранилища и расширение реестра компонентов различными моделями.

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

Здесь мы видим, что наш предыдущий пример отлично работал с сгенерированными типами и дополненными реестрами.

Надеюсь, вам понравился этот пост JS, и мы увидимся в следующий раз.

Ознакомиться с выступлением JS здесь