TypeScript, „супернабор от JS“, улеснява изграждането на поддържаеми, разбираеми и мащабируеми приложения благодарение на голямата сила на проверката на типа.

Обобщенията играят важна роля в TypeScript, тъй като ни позволяват да пишем многократно използваем код, който приема както стойности, така и типове като аргументи.

Генерики във функциите

Generics ни помагат да направим нашия код по-подходящ за многократна употреба. Нека се опитаме да разберем какво представляват генеричните лекарства и защо са ни необходими с помощта на примера по-долу

Моля, обърнете внимание, че в горния фрагмент имаме три функции, които правят почти едно и също нещо. Това е дублиран код и крещи силно, че го прави многократно използваем.

Едно нещо, което можем да направим, е да поставим тип any, така че стойностите от тип String, Number и Person да могат да се извикват като аргументи в една и съща функция. За съжаление, това въвежда повече проблеми, отколкото решава (като цяло, ако планирате да използвате типа any много често, може би е най-добре да го запазите чист JS).

Решаване на „проблема с повторното използване“ с помощта на Generics — Пример:

Функцията converToValueArray получава стойност от избрания тип <T> и връща масив от този тип: Array<T>. Така, например, ако стойността е от тип String, тогава типът на връщането е Array<String>

Нека видим как TypeScript показва грешка, когато дефинираме нашия общ тип.

Моля, обърнете внимание, че в ред 18, след като използваме Generics, ако искаме да получим достъп до възрастта, той показва правилната грешка, което е, което искаме да получим ранна обратна връзка за всякакъв вид грешка.

Изведен тип

Нека дефинираме функция, която приема общ тип.

function convertToArray<T>(args: T): Array<T> {
  return [args];
}

Можем да извикаме функцията по два начина

convertToArray("someString");
convertToArray<String>("someString");

Както виждаме, ако типът не е предаден в <>, тогава типът се извежда автоматично. Изводът за тип поддържа кода по-кратък, но в сложни дефиниции може да се наложи изрично да предадем типа.

Повече от един общ тип

Точно като функционални аргументи, ние можем да предадем повече от един тип, което е независимо от броя на функционалните аргументи. напр

function doStuff<T, U>(name: T): T {
  // ...some process
  return name;
}

Горната функция може да се извика по следния начин:

doStuff<String, Number>("someString");

Генерични класове

Много пъти бихме искали да създадем общ клас, например базови абстрактни класове. Къде можем да предаваме типовете, докато създаваме екземпляри на класове.

Както виждаме, в ред 6 създадохме базов локален клас база данни, който можем да използваме, за да създадем екземпляр за една конкретна таблица и да извършваме операции върху екземпляра на базата данни. Нека напишем контактен клас, който разширява този базов клас, така че да може да наследи някои свойства от родител.

  • Ред 14, когато разширяваме генеричния клас, трябва да предадем два типа в тази база данни. В нашия случай ContactTable и ContactModel.
  • Ред 17: ContactLocalDatabase ще получи функциите от родителския клас и трябва да замени getFormattedData, тъй като това е дефинирано като абстрактна функция в родителския базов клас.
  • Ред 17: Това вече е функцията, която има общ тип, която обсъдихме в първия раздел.

Нека създадем екземпляр на ContactLocalDataBase, за да видим генеричните класове в действие.

  • Ред 1: тъй като сме дефинирали типовете на класа ContactLocalDatabase при използване на ключова дума new, не е необходимо типовете да се предават на основния клас.
  • Ред 3, 11, 13: можем да забележим, че тези функции са от абстрактния клас. Те се държат според общите дефиниции на класа.

Общи ограничения

Досега е съвсем ясно, че генериците са начин за писане на код, така че нашият код да може да поддържа повече от един тип и типът може да бъде предаден като параметър.

Предвид това знание, предаваният тип може да бъде всеки предварително дефиниран тип или сложен тип, дефиниран от потребителя.

Понякога, ако искаме да получим достъп до която и да е функция от генеричната въведена променлива, тя ще изведе грешка.

  • Ред 6: Това е напълно валидна грешка, тъй като данните имат общ тип и могат да бъдат или String, Number, Float или всеки друг тип и предадените данни могат или не могат да имат дължина.

Следователно можем да добавим някои ограничения към всякакви генерични продукти, където TS ще гарантира, че само тези стойности могат да бъдат предадени на функция или клас, които изпълняват ограничението. Нека добавим някои ограничения към нашата обща дефиниция на функция.

  • Ред 4: разширихме типа T, за да има свойство за дължина
  • Ред 5: грешката изчезна, което казва, че дължината на свойството не съществува при тип „T“
  • Ред 10: когато извикаме функцията с число, тя извежда грешка, обяснявайки, че не изпълнява ограничението
  • Ред 12 и 13: когато предаваме валидни данни като String или Array, TS не извежда грешка.

Това е всичко за тази публикация, надявам се, че сте научили основите на Generics и стойността, която генерира.

Ако не знаете основите на Generics, изглежда много сложно.

Надявам се, че времето ви е заслужавало да прочетете тази публикация.

Малко: Създайте по-добри библиотеки с компоненти на потребителския интерфейс

Кажете здравей на Bit. Това е инструмент №1 за разработване на приложения, управлявани от компоненти.

С Bit можете да създадете всяка част от приложението си като „компонент“, който може да се съставя и използва повторно. Вие и вашият екип можете да споделяте инструментариум от компоненти, за да създавате повече приложения по-бързо и последователно заедно.

  • Създавайте и съставяйте „блокове за изграждане на приложения“: UI елементи, пълни функции, страници, приложения, безсървърни или микроуслуги. С всеки JS стек.
  • Лесно споделяйте и използвайте повторно компоненти като екип.
  • Бързо актуализирайте компонентите в проектите.
  • Направете трудните неща прости: Monorepos, системи за проектиране и микро-интерфейси.

Опитайте Bit с отворен код и безплатно→

Научете повече