eduardweb.
TypeScriptÎncepător#typescript#clean-code#javascript#webdev

Utility types în practică: Cum să nu mai duplici interfețele în TypeScript

De Vlad Stancu, 10 aug. 2026 · 9 vizualizări · 3 like-uri

Postat 10 aug. 2026
typescript
interface User {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'user';
  createdAt: Date;
}

// Omit elimina campuri generate automat de backend
type CreateUserInput = Omit<User, 'id' | 'createdAt'>;

// Partial face totul optional pentru request-uri de PATCH
type UpdateUserInput = Partial<CreateUserInput>;

// Pick extrage doar minimul necesar pentru un card simplu
type UserListItem = Pick<User, 'id' | 'name'>;

function createUser(payload: CreateUserInput) {
  return {
    ...payload,
    id: 'usr_123',
    createdAt: new Date()
  };
}

// Inferenta automata a tipului returnat din functie
type CreatedUserResponse = ReturnType<typeof createUser>;

Vezi des proiecte unde există User, UserDTO, CreateUserPayload și UpdateUserPayload, toate definite separat cu aproape aceleași câmpuri. La un SaaS la care am lucrat anul trecut, aveam peste 15 interfețe derivate manual din doar 3 entități principale. Un coșmar la refactoring.

Utility types din TypeScript te scapă exact de mizeria asta și-ți mențin codul DRY fără acrobații arhitecturale.

Pick și Omit: Selecția chirurgicală a câmpurilor

Cel mai des le folosesc la DTO-uri și formulare. În loc să rescrii o interfață pentru formularul de înregistrare unde n-ai nevoie de id sau createdAt, folosești Omit:

type RegisterInput = Omit<User, 'id' | 'createdAt' | 'updatedAt'>;

Dacă vrei exact opusul, adică să extragi doar două sau trei câmpuri dintr-o entitate imensă cu 30 de proprietăți, mergi pe Pick.

Trade-off sincer: Omit e comod, dar are o capcană subtilă. Dacă redenumești o cheie în interfața de bază, Omit nu va da eroare de compilare, ci va ignora string-ul vechi. Pick e mult mai strict și mai sigur la refactoring mare, pentru că te obligă ca cheile specificate să existe pe tipul de origine.

Partial și Required: Formulare de PATCH și validări

Când faci un endpoint de tip PATCH /api/users/123, clientul trimite doar ce vrea să modifice. Nu vrei să-l obligi să trimită tot obiectul complet.

Aici intră Partial<T>, care face toate proprietățile opționale. Pe de altă parte, dacă ai un obiect de configurare unde toate opțiunile au default-uri în runtime, dar vrei ca funcția ta internă să lucreze garantat cu toate câmpurile populate, folosești Required<T>.

Am redus vreo 200 de linii de cod boilerplate într-un API Node.js doar înlocuind interfețele create manual pentru formularele de update cu Partial<CreateDTO>.

ReturnType: Când librăria nu-și exportă tipurile

M-am lovit de asta la un proiect cu un SDK terț prost documentat. Aveam o funcție complexă de factory care returna o structură stufoasă, dar pachetul npm nu exporta interfața returnată.

Decât să ghicești structura și să o scrii de mână (riscând să devină desincronizată la update-uri de pachete), lași TypeScript să o deducă automat:

type ApiResponse = ReturnType<typeof fetchUserData>;

Obții tipul exact de return instant. Dacă echipa schimbă ce returnează funcția aia peste 6 luni, tipul tău se actualizează automat peste tot în aplicație. Zero efort de mentenanță.

Concluzie

Nu mai crea interfețe paralele de mână când ai deja o sursă a adevărului în cod. Folosește Pick când vrei siguranță strictă, Omit pentru cazuri rapide și ReturnType când ești prea leneș să rescrii tipurile furnizate de o funcție.

Voi ce utility types folosiți cel mai des în producție? Ați creat vreodată un utility custom pe care îl purtați după voi din proiect în proiect?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.