Treci la conținutul principal

Tipuri speciale în TypeScript

TypeScript are mai multe tipuri speciale, fiecare cu propriul comportament în sistemul de tipuri.

Le folosești atunci când tipul unei valori nu este cunoscut dinainte sau când trebuie să lucrezi în siguranță cu valori JavaScript precum null.

Notă: Aceste tipuri speciale fac parte din sistemul de tipuri al TypeScript. Ele ajută la scrierea unui cod mai sigur și mai ușor de citit.


Tipul: any

any este cel mai flexibil tip din TypeScript.

Îi spune compilatorului să sară peste verificarea de tip pentru acea variabilă.

Poate fi util, dar folosește-l cu măsură — renunți astfel la siguranța tipurilor oferită de TypeScript.

Când să folosești any:

  • Când migrezi cod JavaScript către TypeScript
  • Când lucrezi cu conținut dinamic al cărui tip nu este cunoscut
  • Când vrei să renunți la verificarea de tip într-un singur loc anume

Notă: any te poate scăpa de erori pentru că dezactivează verificarea de tip, dar TypeScript nu te mai poate proteja, iar uneltele care se bazează pe informațiile de tip, cum ar fi completarea automată, nu mai funcționează.

Ține minte, ar trebui evitat cu „orice” preț...

Exemplu fără any

Acest exemplu nu folosește any. Tipul lui u este dedus ca boolean, așa că atribuirea unui șir de caractere și transmiterea lui către Math.round sunt ambele erori.

Prompt
Arată ce erori apar fără any atunci când o variabilă este folosită ca tipuri diferite. Declară u = true (dedus ca boolean), atribuie-i șirul de caractere „string”, apoi transmite u către Math.round — ambele linii trebuie să nu se compileze: „Type 'string' is not assignable to type 'boolean'” și „Argument of type 'boolean' is not assignable to parameter of type 'number'”.
Ieșire: program TypeScript și rezultatul capturat

Exemplu cu any

Dacă îi dai lui v tipul any, verificarea de tip este dezactivată, așa că același cod se compilează fără erori.

Prompt
Arată că tipul any dezactivează verificarea de tip. Declară v: any = true, atribuie-i șirul de caractere „string”, apoi transmite v către Math.round — niciuna dintre linii nu produce o eroare și nu se afișează nimic.
Ieșire: program TypeScript și rezultatul capturat

Tipul: unknown

unknown este varianta sigură din punctul de vedere al tipurilor a lui any.

Înseamnă „aceasta poate fi orice, deci trebuie să verifici ce este înainte de a o folosi”.

Diferențe importante între unknown și any:

  • unknown trebuie verificat ca tip înainte de utilizare
  • Nu poți citi proprietățile unei valori unknown fără o aserțiune de tip (o conversie)
  • Nu poți apela și nu poți construi o valoare de tip unknown

TypeScript nu te lasă să folosești o valoare unknown până când nu i-ai verificat tipul, așa cum arată exemplul.

Când să folosești unknown:

  • Când lucrezi cu date din surse externe (API-uri, date introduse de utilizator etc.)
  • Când vrei siguranța tipurilor, dar ai nevoie și de flexibilitate
  • Când migrezi de la JavaScript la TypeScript într-un mod sigur

Restrângerea tipului cu unknown: poți restrânge o valoare unknown la un tip concret folosind gărzi de tip precum typeof și Array.isArray, ca în fragmentul de cod de mai jos.

Exemplu

w acceptă un număr, un șir de caractere și un obiect. Apelarea directă a unei metode pe el este o eroare; după o verificare cu typeof și o conversie, apelul este permis și afișează mesajul său.

Prompt
Arată că unknown acceptă orice valoare, dar trebuie verificat sau convertit înainte de utilizare. Declară w: unknown = 1, reatribuie-i un șir de caractere, apoi un obiect cu o metodă runANonExistentMethod care afișează „Gândesc, deci exist” (convertește cu as la un tip obiect). Păstrează un apel direct comentat, care ar produce eroarea „Object is of type 'unknown'”, apoi protejează codul cu typeof w === 'object' && w !== null și apelează metoda printr-o conversie în interiorul lui if.
Ieșire: program TypeScript și rezultatul capturat

Restrângerea lui unknown cu gărzi de tip

În interiorul fiecărei ramuri, TypeScript tratează value ca pe un string sau ca pe un tablou, deci membrii lui pot fi folosiți în siguranță.

script.ts
function processValue(value: unknown) {
  if (typeof value === 'string') {
    // value is now treated as string
    console.log(value.toUpperCase());
  } else if (Array.isArray(value)) {
    // value is now treated as any[]
    console.log(value.length);
  }
}

Tipul: never

never este tipul valorilor care nu apar niciodată.

El spune că ceva nu se întâmplă niciodată sau nu ar trebui să se întâmple niciodată.

Utilizări frecvente pentru never:

  • Funcții care nu returnează niciodată (aruncă întotdeauna o eroare sau rulează la nesfârșit)
  • Gărzi de tip care nu trec niciodată verificarea de tip
  • Verificarea exhaustivității în uniuni discriminate

Fragmentele de cod de mai jos arată never în acțiune, iar exemplul arată ce se întâmplă dacă încerci să îi atribui o valoare.

Când să folosești never:

  • Pentru funcții care nu vor returna niciodată o valoare
  • În gărzi de tip care nu ar trebui să se potrivească niciodată
  • Pentru verificarea exhaustivă a tipurilor în instrucțiuni switch
  • În tipuri generice, pentru a marca anumite cazuri drept imposibile

Tipul never de bază

Nicio valoare nu poate fi atribuită tipului never, așa că atribuirea lui true este o eroare de compilare.

Prompt
Arată că nicio valoare nu poate fi atribuită tipului never. Declară x: never și atribuie-i true — compilatorul trebuie să raporteze „Type 'boolean' is not assignable to type 'never'”.
Ieșire: program TypeScript și rezultatul capturat

Funcție care nu returnează niciodată

O funcție care aruncă întotdeauna o eroare poate declara tipul de retur never.

script.ts
function throwError(message: string): never {
  throw new Error(message);
}

Verificarea exhaustivității cu never

În ramura default, pentru shape nu ar trebui să mai rămână niciun caz, așa că atribuirea lui unei variabile never face ca TypeScript să semnaleze dacă o formă a fost uitată.

script.ts
type Shape = Circle | Square | Triangle;

function getArea(shape: Shape): number {
  switch (shape.kind) {
    case 'circle':
      return Math.PI * shape.radius ** 2;
    case 'square':
      return shape.sideLength ** 2;
    default:
      // TypeScript knows this should never happen
      const _exhaustiveCheck: never = shape;
      return _exhaustiveCheck;
  }
}

Tipul: undefined și null

În TypeScript, undefined și null au fiecare propriul tip, la fel ca string sau number.

În mod implicit, aceste valori pot fi atribuite oricărui alt tip. Poți schimba acest lucru cu verificările stricte de null din TypeScript.

Puncte importante despre undefined și null:

  • undefined înseamnă că o variabilă a fost declarată, dar nu a primit niciodată o valoare
  • null este o atribuire explicită care înseamnă „nicio valoare” sau „niciun obiect”
  • În TypeScript, ambele au propriile tipuri: undefined și null
  • Cu strictNullChecks activat, trebuie să tratezi explicit aceste tipuri

Parametri și proprietăți opționale — un ? după numele unui parametru sau al unei proprietăți îl face opțional, ceea ce adaugă undefined la tipul său.

Operatorul de coalescență nulă și lanțul opțional — ?? oferă o valoare implicită doar atunci când o valoare este null sau undefined, iar ?. citește proprietăți imbricate fără a provoca o eroare atunci când ceva din lanț lipsește.

Important: Aceste tipuri sunt cele mai utile atunci când strictNullChecks este activat în tsconfig.json. Atunci null și undefined pot fi atribuite doar lor înseși și lui any.

Pentru a activa verificările stricte de null, adaugă "compilerOptions": { "strictNullChecks": true } în tsconfig.json.

Utilizare de bază

y are tipul undefined, iar z are tipul null.

Prompt
Arată că undefined și null sunt tipuri de sine stătătoare în TypeScript. Declară y cu tipul undefined conținând undefined și z cu tipul null conținând null. Nu se afișează nimic.
Ieșire: program TypeScript și rezultatul capturat

Parametri și proprietăți opționale

Un parametru opțional este implicit string | undefined, iar o proprietate opțională dintr-o interfață este același lucru cu number | undefined.

script.ts
// Optional parameter (implicitly `string | undefined`)
function greet(name?: string) {
  return `Hello, ${name || 'stranger'}`;
}

// Optional property in an interface
interface User {
  name: string;
  age?: number;  // Same as `number | undefined`
}

Coalescență nulă și lanț opțional

?? revine la 'default' doar pentru null sau undefined, iar ?. citește în siguranță user.address.street.

script.ts
// Nullish coalescing (??) - only uses default if value is null or undefined
const value = input ?? 'default';

// Optional chaining (?.) - safely access nested properties
const street = user?.address?.street;