TypeScript, "надмножество JS", облегчает создание поддерживаемых, понятных и масштабируемых приложений благодаря эффективной возможности проверки типов. Дженерики играют важную роль в TypeScript, поскольку они позволяют нам писать многократно используемый код, принимающий в качестве аргументов как значения, так и типы. Дженерики помогают нам сделать код наиболее пригодным для повторного использования. Давайте попробуем понять, что такое дженерики и зачем они нам нужны, на примере ниже Обратите внимание, что в приведенном выше фрагменте у нас есть три функции, выполняющие практически одно и то же действие. Это дублирующий код, который так и кричит о необходимости сделать его многоразовым. Одна вещь, которую мы бы могли сделать, это поместить тип any, чтобы значения типа String, Number и Person можно было использовать в качестве аргументов в одной и той же функции. К сожалению, это вызывает больше проблем, чем решает (в общем, если вы планируете использовать тип any очень часто, то, возможно, лучше оставить его исключительно в JS). Решение "проблемы повторного использования" с помощью дженериков — пример: Функция converToValueArray получает значение выбранного типа <T> и возвращает массив этого типа: Array<T> . Так, например, если значение имеет тип String, то возвращаемый тип будет Array<String>. Давайте посмотрим, как TypeScript показывает ошибку, когда мы определяем наш дженерик-тип. Обратите внимание, в строке 18, после использования дженериков, если мы хотим получить доступ к age (возрасту), он показывает соответствующую ошибку, что нам и нужно для получения своевременного фидбека на любую неточность. Давайте определим функцию, которая принимает дженерик-тип. Мы можем вызвать функцию двумя способами Как мы видим, если тип не передан в <>, то он выводится автоматически. Вывод типа делает код короче, но в сложных определениях может потребоваться явная передача типа. Точно так же, как аргументы функции, мы можем передавать более одного типа, что не зависит от количества аргументов функции. Например Вышеуказанная функция может быть вызвана следующим образом: Много раз нам требовалось бы создать дженерик-класс, например, абстрактные Base (базовые) классы. В них мы можем передавать типы при создании экземпляров классов. Как видно, в строке 6 мы создали базовый локальный класс базы данных, который мы можем использовать для создания экземпляра одной конкретной таблицы и выполнения операций над экземпляром базы данных. Давайте напишем класс contact, который расширяет этот базовый класс, чтобы он мог наследовать некоторые свойства от родителя. В строке 14, при расширении дженерик-класса, в данной базе данных мы должны передать два типа. В нашем случае ContactTable и ContactModel. Строка 17: База данных ContactLocalDatabase получит функции из родительского класса и должна переопределить функцию getFormattedData, поскольку она определена как абстрактная функция в родительском базовом классе. Строка 17: Теперь это функция, имеющая дженерик-тип, о котором мы говорили в первом разделе. Давайте создадим экземпляр ContactLocalDataBase, чтобы увидеть дженерики класса в действии. Строка 1: поскольку мы определили типы класса ContactLocalDatabase при использовании ключевого слова new, типы не нужно передавать в базовый класс. Строки 3, 11, 13: мы можем заметить, что эти функции принадлежат абстрактному классу. Они ведут себя в соответствии с определениями дженерик-класса. До сих пор было понятно, что дженерики — это способ написания кода таким образом, что наш код может поддерживать более одного типа и тип может быть передан в качестве параметра. Исходя из этого, передаваемый тип может быть любым предопределенным или сложным пользовательским типом. Иногда, если мы хотим получить доступ к какой-либо функции из дженерик-типизированной переменной, это приведет к ошибке. Строка 6: Это вполне допустимая ошибка, так как у данных дженерик-тип. Они могут быть String, Number, Float или любым другим типом, а передаваемые данные могут как учитывать длину, так и нет. Следовательно, мы можем добавить некоторые ограничения к любым дженерикам, где TS будет гарантировать, что только те значения могут быть переданы в функцию или класс, которые выполняют ограничивающее условие. Давайте добавим некоторые ограничения к определению нашей дженерик-функции. Строка 4: мы расширили тип T, чтобы он имел свойство length (длина); Строка 5: исчезла ошибка, которая говорила, что свойство length не существует для типа 'T'; Строка 10: когда мы вызываем функцию с числом, она выдает ошибку, объясняя, что не выполняется условие ограничения; Строки 12 и 13: когда мы передаем корректные данные, такие как String или Array, TS не выдает ошибку. Завтра состоится открытое занятие «Обзор технологий для построения API», на котором рассмотрим несколько протоколов клиент-серверных приложений. На примере увидим сильные стороны и недостатки. Регистрация для всех желающих здесь.