Введение
TypeScript, строго типизированный надмножество JavaScript, хорошо известен своей способностью улучшать масштабируемость, удобочитаемость и ремонтопригодность приложений. Одной из выдающихся особенностей TypeScript является поддержка дженериков, инструмента, который позволяет разработчикам создавать компоненты, которые могут работать с различными типами, а не с одним.
В этой статье мы подробно рассмотрим дженерики в TypeScript, предоставив информацию об их реализации и полезности с несколькими иллюстративными примерами.
Общие сведения
Дженерики похожи на переменные, но для типов. Они позволяют нам зафиксировать тип, переданный в качестве параметра, давая нам возможность использовать этот тип в различных местах, где это необходимо. Это выводит наш код TypeScript на новый уровень повторного использования и динамичности.
Например, представьте себе сценарий, в котором вы должны создать функцию, возвращающую тот же тип, что и передаваемый аргумент. Без дженериков вы могли бы склониться к использованию типа «любой». Но это не безопасно для типов. Дженерики предлагают решение.
function identity<T>(arg: T): T { return arg; } let output = identity<string>("myString");
В приведенном выше примере <T>
— это переменная типа — своего рода переменная, которая работает с типами, а не со значениями.
Общие переменные
TypeScript позволяет вам работать с универсальными переменными точно так же, как с обычными переменными. Однако универсальные переменные действуют на типы, а не на значения.
function identity<T>(arg: T): T { console.log(arg.length); // Error: T doesn't necessarily have a .length return arg; }ty
В приведенном выше примере вы получите сообщение об ошибке, поскольку не все типы имеют свойство .length
. Чтобы это работало, мы можем указать, что T
должно быть ограничено типами, у которых есть свойство .length
.
interface Lengthy { length: number; } function loggingIdentity<T extends Lengthy>(arg: T): T { console.log(arg.length); // Now we know it has a .length property, so no more error return arg; } loggingIdentity("hello world"); // OK loggingIdentity(3); // Error: number doesn't have a .length property
Общие классы
Универсальный класс — это класс с формой, аналогичной универсальному интерфейсу. Универсальные классы имеют список параметров универсального типа в угловых скобках (<>
) после имени класса.
class GenericNumber<T> { zeroValue: T; add: (x: T, y: T) => T; } let myGenericNumber = new GenericNumber<number>(); myGenericNumber.zeroValue = 0; myGenericNumber.add = function(x, y) { return x + y; };
Общие ограничения
В TypeScript вы также можете создавать ограничения для универсальных типов. Ограничения ограничивают диапазон типов, которые может представлять переменная типа.
interface Lengthwise { length: number; } function loggingIdentity<T extends Lengthwise>(arg: T): T { console.log(arg.length); // OK, because T extends Lengthwise return arg; }
Заключение
Обобщения в TypeScript — это мощная функция, которая позволяет разработчикам создавать гибкие и повторно используемые компоненты, которые не только безопасны для типов, но и помогают поддерживать целостность кода с течением времени. Поначалу они могут показаться немного сложными, но как только вы их поймете и начнете использовать, они станут незаменимой частью вашего набора инструментов TypeScript.
Помните, что практика является ключом к освоению дженериков. Итак, возьмите приведенные выше примеры, настройте их, сломайте и исправьте снова, чтобы узнать больше о дженериках.
Удачного кодирования!