Lecții din modul (2/2)
Generice fundamentale
Generics (programare generică) sunt una dintre cele mai puternice caracteristici ale TypeScript. Acestea vă permit să scrieți componente, funcții și interfețe flexibile și reutilizabile care pot funcționa cu diferite tipuri de date, menținând în același timp siguranța maximă a tipului și evitând utilizarea any.
Funcții generice
Gândiți-vă la un generic ca la o variabilă pentru tipuri. Să considerăm o funcție care returnează valoarea transmisă ca argument:
function identity<T>(arg: T): T {
return arg;
}Litera T (prescurtare pentru Type) este un substituent pentru tip. Când apelăm identity, TypeScript captează tipul argumentului transmis și setează automat T la acel tip:
const str = identity<string>('Hello'); // T is string
const num = identity(42); // T is number (automatically inferred!)Interfețe și aliasuri generice
Genericurile pot fi, de asemenea, aplicate la interfețe și alias-uri de tip pentru a defini containere generice sau structuri de date:
interface Box<T> {
content: T;
}
const stringBox: Box<string> = { content: 'TypeScript' };
const numberBox: Box<number> = { content: 42 };Parametri de tip multiplu
Putem defini funcții sau tipuri care utilizează mai multe variabile de tip (de exemplu, T și U):
function mergeObjects<T, U>(obj1: T, obj2: U): T & U {
return { ...obj1, ...obj2 };
}Constrângeri generice
Uneori vrem să limităm tipurile acceptate de un generic. Putem folosi cuvântul cheie extends pentru a adăuga o constrângere.
De exemplu, dacă dorim ca tipul generic să aibă întotdeauna o proprietate length (cum ar fi șiruri de caractere sau matrice):
interface HasLength {
length: number;
}
function logLength<T extends HasLength>(arg: T): void {
console.log(arg.length); // Safe! We know arg has 'length'
}
logLength('Hello'); // Valid
logLength([1, 2, 3]); // Valid
// logLength(42); // Error: number does not have a length property!Încercați-l singur
Exercițiul 1: Funcția de identitate generică
Completați funcția de identitate generică astfel încât să accepte un parametru de valoare de tip generic T și să-l returneze fără modificare.
Afișează indiciu
Tipul returnat trebuie să fie de același tip generic T ca și parametrul.
Soluție disponibilă după 3 încercări
Exercițiul 2: Box Wrapper generic
Definiți o interfață generică numită Box care acceptă un parametru de tip T și are o singură proprietate numită conținut de tip T.
Afișează indiciu
Utilizați interfața Box<T> { conținut: T; } sintaxă.
Soluție disponibilă după 3 încercări
Exercițiul 3: Constrângere generică
Scrieți o funcție generică numită getLength care acceptă un parametru arg. arg trebuie să fie constrâns la o interfață care are o proprietate de lungime (număr). Funcția trebuie să returneze arg.length.
Afișează indiciu
Declarați funcția ca getLength<T extins HasLength>(arg: T): număr și returnează arg.length.
Soluție disponibilă după 3 încercări
Exercițiul 4: Perechea generică
Definiți o interfață generică Pair<T, U> cu două proprietăți: prima de tip T și a doua de tip U. Apoi, creați o funcție generică makePair care acceptă primul (de tipul T) și al doilea (de tipul U) și returnează un obiect care implementează Pair<T, U>.
Afișează indiciu
Utilizați sintaxa pentru doi parametri generici Pair<T, U> și definiți makePair în consecință.
Soluție disponibilă după 3 încercări