Ce face constrângeri generice (extends)
Un generic simplu, <T>, poate fi orice, deci în funcție nu poți folosi nicio proprietate a lui. O constrângere, <T extends { length: number }>, spune: „T poate fi orice tip care are length”. Acum poți citi x.length, iar apelurile cu un tip fără length sunt erori.
Rezultatul păstrează totuși tipul exact al argumentului: dacă dai un string, T este string, nu { length: number }. Asta este diferența față de un parametru cu tipul constrângerii.
O combinație foarte folosită este <T, K extends keyof T>: K poate fi doar numele unei proprietăți din T, iar T[K] este tipul acelei proprietăți (vezi keyof și indexed access).
Exemple
Exemplul 1: Orice tip care are length
function celMaiLung<T extends { length: number }>(a: T, b: T): T {
return a.length >= b.length ? a : b;
}
console.log(celMaiLung("Iași", "Timișoara"));
console.log(celMaiLung([1, 2, 3], [4, 5]));
const rezultat = celMaiLung("Ana", "Ioana"); // tipul rămâne string
console.log(rezultat.toUpperCase());
Rezultat
Timișoara
[ 1, 2, 3 ]
IOANA
Exemplul 2: Cheie care trebuie să existe
K extends keyof T acceptă doar "nume", "oras" sau "nota". Rezultatul are tipul proprietății alese: pentru "nota" este number[], deci merge în Math.max.
function coloana<T, K extends keyof T>(lista: T[], cheie: K): T[K][] {
return lista.map((x) => x[cheie]);
}
const elevi = [
{ nume: "Mihai", oras: "Cluj", nota: 8 },
{ nume: "Ana", oras: "Iași", nota: 10 },
{ nume: "Ioana", oras: "Brașov", nota: 9 },
];
const nume = coloana(elevi, "nume"); // string[]
const note = coloana(elevi, "nota"); // number[]
console.log(nume, coloana(elevi, "oras"));
console.log(note, Math.max(...note));
Rezultat
[ 'Mihai', 'Ana', 'Ioana' ] [ 'Cluj', 'Iași', 'Brașov' ]
[ 8, 10, 9 ] 10
Exemplul 3: Argument care nu respectă constrângerea
function celMaiLung<T extends { length: number }>(a: T, b: T): T {
return a.length >= b.length ? a : b;
}
console.log(celMaiLung(10, 200));
Eroarea afișată de tsc
exemplu.mts(4,24): error TS2345: Argument of type 'number' is not assignable to parameter of type '{ length: number; }'.
Greșeli frecvente
- Scrii
function f<T>(x: T) { return x.length; }fără constrângere. tsc dă Property ‘length’ does not exist on type ‘T’. - Returnezi un obiect nou de tipul constrângerii dintr-o funcție care promite
T. tsc refuză, pentru căTpoate fi un subtip cu mai multe proprietăți.
Comenzi înrudite
generics (<T>): Parametri de tip: o funcție sau clasă scrisă o dată, care funcționează cu orice tip și păstrează tipul exact.keyof: keyof T dă union-ul numelor de proprietăți ale lui T, de exemplu „nume” | „oras”.indexed access (T[K]): T[„cheie”] dă tipul unei proprietăți din T; T[number] dă tipul elementelor unui tablou.extends: O clasă moștenește câmpurile și metodele altei clase; o interfață preia proprietățile altor interfețe.conditional types: Un tip care alege între două variante după o condiție: T extends U ? X : Y.