TypeScript pentru începători, Partea 5 Generic

Al doilea tutorial din seriile noastre TypeScript pentru începători sa concentrat pe tipurile de date de bază disponibile în TypeScript. Verificarea tipului în TypeScript ne permite să ne asigurăm că variabilele din codul nostru pot avea doar anumite tipuri de valori atribuite acestora. În acest fel, putem evita multe greșeli în timp ce scriem coduri, deoarece IDE-ul ne va putea spune când efectuăm o operație pe un tip pe care nu îl suportă. Acest lucru face ca tipul să verifice una dintre cele mai bune caracteristici ale TypeScript.

În acest tutorial, ne vom concentra pe o altă caracteristică importantă a acestei generice de limbi. Cu generice, TypeScript vă permite să scrieți cod care poate acționa pe o varietate de tipuri de date, în loc să fie limitat la unul singur. Veți învăța despre necesitatea generică în general și despre cum este mai bine decât să utilizați orice tipul de date disponibil în TypeScript.

Nevoia de generice

Dacă nu sunteți familiarizați cu medicamentele generice, s-ar putea să vă întrebați de ce avem nevoie de ele. În această secțiune, vă voi răspunde la această întrebare. Să începem prin scrierea unei funcții care va returna un element aleator dintr-o serie de numere.

funcția randomIntElem (array: numărul []): numărul let randomIndex = Math.floor (Math.random () * theArray.length); returnați TheArray [randomIndex];  permiteți pozițiile: numărul [] = [103, 458, 472, 458]; permite randomPosition: number = randomIntElem (pozitii);

randomElem funcția pe care tocmai am definit-o ia un număr de numere ca singurul său parametru. Tipul de retur al funcției a fost, de asemenea, specificat ca număr. Noi folosim Math.random () pentru a returna un număr aleator mobil cu puncte variabile între 0 și 1. Înmulțind-o cu lungimea unei matrice date și apelând Math.floor () rezultatul ne dă un indice aleatoriu. Odată ce avem indicele aleatoriu, vom returna elementul la acel indice specific.

După ceva timp, să presupunem că trebuie să obțineți un element de șir aleatoriu dintr-o serie de șiruri de caractere. În acest moment, puteți decide să creați o altă funcție care vizează în mod specific șiruri de caractere.

funcția randomStrElem (array: string []): șir permite randomIndex = Math.floor (Math.random () * theArray.length); returnați TheArray [randomIndex];  permiteți culorilor: șir [] = ['violet', 'indigo', 'albastru', 'verde']; lăsați randomColor: string = randomStrElem (culori);

Ce se întâmplă dacă trebuie să selectați un element aleator dintr-o matrice a unei interfețe pe care ați definit-o? Crearea unei noi funcții de fiecare dată când doriți să obțineți un element aleator dintr-o serie de tipuri diferite de obiecte nu este fezabilă.

O soluție pentru această problemă este de a seta tipul de parametru de matrice care este transmis funcțiilor ca orice[]. În acest fel, puteți să vă scrieți funcția doar o singură dată și aceasta va funcționa cu o matrice de toate tipurile.

funcția randomElem (Array: orice []): orice let randomIndex = Math.floor (Math.random () * theArray.length); returnați TheArray [randomIndex];  permiteți pozițiile = [103, 458, 472, 458]; permite randomPosition = randomElem (poziții); permiteți culorilor = ['violet', 'indigo', 'blue', 'green']; permiteți randomColor = randomElem (culori);

După cum puteți vedea, putem folosi funcția de mai sus pentru a obține poziții aleatorii, precum și culori aleatorii. O problemă majoră cu această soluție este că veți pierde informațiile despre tipul de valoare care este returnat. 

Înainte, eram siguri că randomPosition ar fi un număr și culoare aleatorie ar fi un șir. Acest lucru ne-a ajutat să folosim aceste valori în consecință. Acum, tot ce știm este că elementul returnat ar putea fi de orice tip. În codul de mai sus, am putea specifica tipul de culoare aleatorie a fi un număr și încă nu obține nici o eroare.

// Acest cod se va compila fără o eroare. permiteți culorilor: șir [] = ['violet', 'indigo', 'albastru', 'verde']; lăsați randomColor: number = randomElem (culori);

O soluție mai bună pentru a evita dublarea codului, păstrând în același timp informațiile de tip, este de a folosi generice. Aici este o funcție generică care returnează elemente aleatoare dintr-un matrice.

funcția randomElem(TheArray: T []): T lăsăm randomIndex = Math.floor (Math.random () * theArray.length); returnați TheArray [randomIndex];  permiteți culorilor: șir [] = ['violet', 'indigo', 'albastru', 'verde']; permiteți randomColor: string = randomElem (culori);

Acum, voi primi o eroare dacă încerc să schimb tipul de culoare aleatorie din şir la număr. Acest lucru demonstrează că utilizarea de generice este mult mai sigură decât utilizarea orice tip în astfel de situații.

Utilizarea generice poate părea foarte limitat

Secțiunea anterioară a discutat despre modul în care puteți utiliza generice în loc de orice tastați pentru a scrie o singură funcție și pentru a evita sacrificarea beneficiilor verificării de tip. O problemă cu funcția generică pe care am scris-o în secțiunea anterioară este că TypeScript nu ne va permite să efectuăm o mulțime de operații asupra variabilelor transmise acesteia. 

Acest lucru se datorează faptului că TypeScript nu poate face presupuneri cu privire la tipul de variabilă care va fi transmisă funcției noastre generice în prealabil. Ca rezultat, funcția noastră generică poate utiliza doar acele operații care se aplică tuturor tipurilor de date. Exemplul următor ar trebui să facă acest concept mai clar.

funcția removeChar (String: șirul, șirul Char: șir): șirul let theRegex = noul RegExp (theChar, "gi"); returnați TheString.replace (theRegex, ");

Funcția de mai sus va elimina toate aparițiile caracterului specificat din șirul dat. S-ar putea să doriți să creați o versiune generică a acestei funcții, astfel încât să puteți elimina și cifrele specifice dintr-un număr dat, precum și caracterele dintr-un șir. Iată funcția generică corespunzătoare.

funcția removeIt(intrarea: T, aIt: șir): T let theRegex = noua RegExp (theIt, "gi"); returnațiInput.replace (theRegex, ");

removeChar nu ți-a arătat o eroare. Cu toate acestea, dacă utilizați a inlocui interior scoateți-l,TypeScript vă va spune asta a inlocui nu există pentru tipul "T". Acest lucru se datorează faptului că TipScript nu mai poate presupune acest lucru Intrarea va fi un șir.

Această restricție privind utilizarea diferitelor metode într-o funcție generică vă poate determina să credeți că conceptul de generice nu va fi de mult folos atunci. Nu există prea multe lucruri pe care le puteți face cu o mână de metode care trebuie să se aplice tuturor tipurilor de date pentru a le utiliza în interiorul unei funcții generice.

Un lucru important pe care ar trebui să-l amintiți în acest moment este că în general nu trebuie să creați funcții care să fie utilizate cu tot felul de tipuri de date. Este mai frecvent să creați o funcție care va fi utilizată cu un anumit set sau o gamă de tipuri de date. Această constrângere asupra tipurilor de date face ca funcțiile generice să fie mult mai utile.

Creați funcții generice utilizând constrângerile

Genericul scoateți-l din secțiunea anterioară a arătat o eroare deoarece a inlocui metoda din interiorul acestuia este menită a fi utilizată cu șiruri, în timp ce parametrii care îi sunt transmiși pot avea orice tip de date. 

Puteți utiliza funcția extinde cuvinte cheie pentru a constrânge tipurile de date care sunt transmise unei funcții generice în TypeScript. in orice caz, extinde este limitat doar la interfețe și clase. Aceasta înseamnă că cele mai multe funcții generice pe care le creați vor avea parametri care extind o interfață de bază sau o clasă. 

Aici este o funcție generică care imprimă numele oamenilor, membrilor familiei sau celebrităților care i-au fost transmise.

interfață Persoane nume: șir interfață Familie nume: șir, vârstă: număr, relație: șir interfață Celebritate extinde Oameni profession: string function printName(input: T): void console.log ('Numele meu este $ theInput.name');  să serena: Celebrity = name: 'Serena Williams', meserie: 'Tennis Player' printName (serena);

În exemplul de mai sus, am definit trei interfețe și fiecare dintre ele are a Nume proprietate. Genericul printeaza numele funcția pe care am creat-o va accepta orice obiect care se extinde oameni. Cu alte cuvinte, puteți trece la această funcție fie o familie, fie un obiect de celebritate, și va imprima numele său fără plângeri. Puteți defini mai multe interfețe, și atâta timp cât acestea au un a Nume proprietate, veți putea folosi printeaza numele fără nici o problemă.

Acesta a fost un exemplu foarte simplu, dar puteți crea funcții generice mai utile după ce vă simțiți mai confortabil cu întregul proces. De exemplu, puteți crea o funcție generică care calculează valoarea totală a diferitelor elemente vândute într-o anumită lună, atâta timp cât fiecare element are o Preț proprietate pentru a stoca prețul și a vândut proprietate care stochează numărul de articole vândute. Utilizând generice, veți putea utiliza aceeași funcție atâta timp cât elementele extind aceeași interfață sau aceeași clasă.

Gândurile finale

În acest tutorial, am încercat să acoperim elementele de bază ale genericelor în TypeScript într-o manieră prietenoasă pentru începători. Am inceput articolul discutandu-ne despre necesitatea generica. După aceea, am aflat despre modul corect de utilizare a genericelor pentru a evita dublarea codului, fără a sacrifica capacitatea de verificare a tipului. Odată ce înțelegeți elementele de bază discutate aici, puteți citi mai multe despre medicamentele generice în documentația oficială.

Dacă aveți întrebări legate de acest tutorial, vă vom răspunde cu plăcere la comentarii.

Cod