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

Дженерики:

Простой способ думать о дженериках — обращаться с ними как с заполнителями для типов.

Например, давайте предположим функцию, которая используется для добавления отзывов к объекту на нашей выдуманной платформе электронной коммерции. Этот объект может быть продуктом, продавцом или экземпляром доставки.

Конечно, мы могли бы иметь отдельные функции для добавления оценок к каждому типу объектов и иметь сильно дублированную и избыточную кодовую базу с копированием/вставкой, выполняемой слева и справа; или мы могли бы решить иметь чистую кодовую базу, используя дженерики следующим образом:

В приведенном выше примере T является универсальным, и мы наложили на него ограничение, чтобы он принимал только RatableEntity типов, которые могут быть продуктом, продавцом, экземпляром доставки, ответственным за доставку и т. д. без ограничения T так же хорошо, как any .

RatableEntity может быть следующим интерфейсом:

Функция addRating, которую мы создали выше, называется generic function.

Общие интерфейсы и классы:

В TypeScript также можно создавать универсальные классы и универсальные интерфейсы. На самом деле интерфейс Array — это built-in generic interface в TypeScript.

Вот почему мы можем сделать что-то вроде следующего с массивами:

let numericArray = new Array<number>();
let stringArray = new Array<string>();
let myCustomObjectArray = new Array<MyCustomType>();

Приведенный выше код возможен, потому что Array<T> — это определение интерфейса, которое представляет собой generic interface.

Общий интерфейс:

Давайте напишем наш собственный общий интерфейс в этом разделе, чтобы лучше понять эту идею:

Представьте, что нашему приложению необходимо вести учет сотрудников и их руководителей. Давайте сначала создадим интерфейс Employee следующим образом:

Department — это настраиваемый пользовательский тип, который определяется следующим образом:

type Department = "HR" | "Engineering" | "Sales" | "Finance"

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

Теперь мы можем использовать общий интерфейс Employee следующим образом:

Общий класс:

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

Давайте создадим общий classQueue<T>, который будет нашей собственной реализацией очереди в Typescript, следующим образом:

Теперь мы могли бы использовать приведенный выше универсальный класс для создания различных экземпляров очередей однородных типов данных следующим образом:

let numericQueue = new Queue<number>();
let stringQueue = new Queue<string>();

Таким образом, мы можем повторно использовать один и тот же класс Queue для создания разных типов очередей с разными типами данных.

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

Вывод:

Таким образом, в этой статье мы рассмотрели некоторые расширенные варианты использования дженериков TypeScript, таких как generics with constraints, generic functions, generic interfaces и generic classes.

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