eduardweb.
TypeScriptÎncepător#typescript#backend#webdev

De ce scrii interfețe duplicate în TypeScript? Folosește Utility Types

De George Iliescu, 25 mai 2026 · 5 vizualizări · 3 like-uri

Postat 25 mai 2026
typescript
interface User {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'user';
  passwordHash: string;
  createdAt: Date;
}

// 1. Pick: Păstrăm doar ce poate edita userul la profil
type UpdateProfilePayload = Pick<User, 'name' | 'email'>;

// 2. Omit: Trimitem datele către front-end fără hash-ul de parolă
type UserResponse = Omit<User, 'passwordHash'>;

// 3. Combinație: ID obligatoriu + restul câmpurilor opționale pentru update
type SafeUpdatePayload = Pick<User, 'id'> & Partial<Omit<User, 'id'>>;

// 4. ReturnType: Extragem tipul returnat de o funcție de sesiune
function createSession(user: UserResponse) {
  return {
    token: "jwt-token-generat-aici",
    user,
    expiresAt: Date.now() + 3600 * 1000
  };
}
type SessionInfo = ReturnType<typeof createSession>;

Am văzut prea des proiecte unde aceeași entitate este definită în cinci interfețe diferite pentru diverse stări: una pentru baza de date, alta pentru payload-ul de API, alta pentru formularul din front-end. Este o pierdere de timp și o sursă garantată de bug-uri. TypeScript are deja utilitare geniale în engine-ul său, gata să facă munca grea pentru tine.

La un proiect cu peste 8k de utilizatori activi, aveam o tabelă uriașă de User în Postgres. Când am început să scriem endpoint-urile de update și profile view, codul devenise plin de interfețe duplicate redundante. Atunci am decis să facem curățenie folosind utilitarele native. Am salvat cam 30% la build time și am eliminat complet desincronizările de tipuri.

Pick și Omit: Cum să tai din interfețe fără să pierzi siguranța

Cea mai comună problemă: ai nevoie doar de câteva câmpuri pentru o acțiune specifică. De exemplu, când un utilizator își editează profilul, nu vrei să-i permiți să trimită câmpuri precum id, role sau createdAt.

Aici intervine Pick. Îi spui exact ce proprietăți vrei să păstrezi din tipul de bază.

La polul opus avem Omit. Îl folosești când vrei să excluzi ceva sensibil. De exemplu, când trimiți datele utilizatorului către front-end, vrei să elimini passwordHash.

Trade-off sincer: Omit este comod, dar poate fi periculos. Dacă adaugi un câmp nou sensibil în baza de date (cum ar fi isBanned), și uiți să updatezi lista din Omit, câmpul va fi expus automat în tipul rezultat. De aceea, pentru API-uri publice, prefer oricând Pick – este mult mai sigur fiindcă e de tip "opt-in".

Partial și Required pentru formulare dinamice

Când faci un update parțial prin HTTP PATCH, toate câmpurile din payload devin opționale. În loc să scrii o interfață nouă plină de semne de întrebare, folosești Partial<User>.

Dar fii atent la o capcană des întâlnită: Partial face absolut totul opțional. Dacă ai nevoie ca id-ul să fie obligatoriu pentru a ști pe cine updatezi, dar restul câmpurilor să fie opționale, poți combina utilitarele așa cum am arătat în exemplul de cod atașat.

Required face exact inversul. Îl folosesc des în teste sau în funcții de inițializare unde vreau să mă asigur că, deși în mod normal un obiect are câmpuri opționale, în acel context specific am absolut toate datele completate.

ReturnType: Când codul tău dictează tipul

Am avut cazul unui factory complex de securitate care genera configurări dinamice pentru token-uri JWT. Structura returnată era un obiect imbricat destul de greu de definit manual. În loc să stau să scriu o interfață mamut care trebuia modificată la fiecare update de logică, am extras tipul direct din funcție folosind ReturnType<typeof generateConfig>.

TypeScript citește ce returnează funcția ta și generează tipul în mod dinamic. Dacă schimbi logica funcției, tipul se updatează de la sine peste tot în proiect.

Voi cum gestionați interfețele astea mari? Preferați să le duplicați manual ca să fie "mai clare" la citire, sau folosiți utilitarele din limbaj?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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