webroad.online
  1. 1Web
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Unelte
  8. 8React
  9. 9State management
  10. 10Next.js
  11. 11Formulare
  12. 12Date și backend
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Animații
  16. 16Testare
  17. 17Arhitectură
TypeScript · Lecția 4 din 6

Generics

Tipuri cu parametri, constrângeri cu extends, keyof și T[K].

Actualizat

Ce sunt generics

Generics sunt tipuri cu parametri. Așa cum o funcție primește valori ca parametri, un generic primește tipuri ca parametri.

Problema pe care o rezolvă:

function first(arr: any[]): any { return arr[0] }
const n = first([1, 2])       // any — ai pierdut informația că e number

function first<T>(arr: T[]): T | undefined { return arr[0] }
const m = first([1, 2])       // number ✓
const s = first(['a'])        // string ✓

T e un parametru de tip — un loc gol completat automat de TS din argumente. Funcția rămâne una singură, dar tipul rezultatului urmează tipul inputului.

Le folosești deja

const ids: Array<number> = []                 // = number[]
const users = new Map<string, User>()
const [count, setCount] = useState<number>(0)
const res: Promise<User> = getUser()

Constrângeri cu extends

Uneori T nu poate fi chiar orice — trebuie să aibă ceva anume:

function longest<T extends { length: number }>(a: T, b: T): T {
  return a.length >= b.length ? a : b
}

longest('abc', 'de')        // ✓ string are length
longest([1, 2], [3])        // ✓ array are length
longest(10, 20)             // ✗ number nu are length

keyof și acces după cheie

function pluck<T, K extends keyof T>(items: T[], key: K): T[K][] {
  return items.map(item => item[key])
}

pluck(users, 'email')       // string[]
pluck(users, 'emial')       // ✗ typo prins

keyof T = union-ul cheilor lui T; T[K] = tipul valorii de la cheia K.

Tipuri generice

Nu doar funcțiile pot fi generice:

type ApiResponse<T> =
  | { ok: true; data: T }
  | { ok: false; error: string }

type Paginated<T> = { items: T[]; page: number; total: number }

const res: ApiResponse<Paginated<Product>> = await api('/products')

Când folosești generics

Situație Generic?
funcție care lucrează la fel cu orice tip (first, groupBy, pluck) da
tip „container” (răspuns API, paginare, state de formular) da
componentă React reutilizabilă pentru orice tip de item (List<T>, Select<T>) da
funcție care lucrează doar cu User nu — scrie User

Semn că exagerezi: T apare o singură dată în semnătură. Atunci nu e nevoie de generic.

Pe scurt

  • Generic = tip cu parametru; păstrează legătura dintre tipul inputului și al outputului.
  • extends impune ce trebuie să aibă T; keyof T + T[K] pentru acces după cheie.
  • Folosește-le pentru utilitare și containere, nu peste tot.

Surse oficiale

Exerciții

Ți-a fost utilă pagina?

Un click — fără cont.