Adnotări de tip și inferență
TypeScript îți oferă două moduri de a lucra cu tipurile:
- Tipizare explicită: scrii singur tipul unei variabile.
- Inferență de tip: TypeScript deduce tipul din valoarea pe care o atribui.
Când folosești fiecare abordare
- Folosește tipuri explicite pentru:
- Parametrii și tipurile returnate ale funcțiilor
- Obiecte literale
- Cazurile în care valoarea inițială ar putea să nu fie tipul final
- Folosește inferența de tip pentru:
- Declarații simple de variabile cu atribuire imediată
- Cazurile în care tipul este evident din context
Adnotări de tip explicite
Tipizarea explicită înseamnă că îi spui lui TypeScript exact ce tip trebuie să aibă o variabilă. Scrii două puncte și tipul după numele variabilei.
Bună practică: Folosește tipuri explicite pentru parametrii și tipurile returnate ale funcțiilor. Astfel codul este mai ușor de întreținut și se documentează singur.
Tipuri explicite de bază
Fiecare variabilă are tipul scris explicit: string, number, boolean și number[] (un tablou de numere).
greeting ca string ("Salut, TypeScript!"), userCount ca number (42), isLoading ca boolean (true) și scores ca number[] ([100, 95, 98]), fiecare precedată de un comentariu care numește tipul. Nu se afișează nimic.
Ieșire: program TypeScript și rezultatul capturat
// Șir de caractere
let greeting: string = "Salut, TypeScript!";
// Număr
let userCount: number = 42;
// Boolean
let isLoading: boolean = true;
// Tablou de numere
let scores: number[] = [100, 95, 98];
Funcție cu tipuri explicite
Atât parametrul, cât și valoarea returnată sunt tipizate ca string. TypeScript verifică fiecare apel, așa că transmiterea numărului 42 este o eroare de compilare.
string explicit și tip returnat string, precum și eroarea care apare când tipul argumentului este greșit.
Definește greet(name: string): string care returnează un salut construit cu un șablon literal, apeleaz-o cu "Alice" (corect), apoi apeleaz-o cu numărul 42 — această linie nu trebuie să compileze, cu eroarea "Argument of type '42' is not assignable to parameter of type 'string'".
Ieșire: program TypeScript și rezultatul capturat
// Funcție cu tipuri explicite pentru parametru și pentru valoarea returnată
function greet(name: string): string {
return `Salut, ${name}!`;
}
// TypeScript se asigură că transmiți argumentul de tipul corect
greet("Alice"); // OK
greet(42); // Eroare: Argument of type '42' is not assignable to parameter of type 'string'
Inferența de tip
TypeScript poate deduce (infera) tipul unei variabile din valoarea ei inițială, așa că nu trebuie să îl scrii tu.
Notă: Inferența de tip funcționează cel mai bine atunci când o variabilă primește valoarea chiar în momentul declarării.
O variabilă declarată fără valoare are implicit tipul any, dacă nu activezi strictNullChecks în tsconfig.json.
Când strălucește inferența — obiectele literale sunt un bun exemplu: TypeScript află întreaga formă a obiectului din proprietățile lui.
Atenție: Inferența de tip este comodă, dar scrierea explicită a tipurilor poate face codul mai ușor de întreținut, mai ales în proiecte mari sau în API-uri publice.
Inferență de tip de bază
Pe variabile nu este scris niciun tip. TypeScript deduce string, number, boolean[] și tipul returnat number pentru add.
username = "alice" (dedus string), score = 100 (dedus number), flags = [true, false, true] (dedus boolean[]) și o funcție add(a: number, b: number) al cărei tip returnat este dedus ca number; adaugă deasupra fiecăreia un comentariu care precizează tipul dedus. Nu se afișează nimic.
Ieșire: program TypeScript și rezultatul capturat
// TypeScript deduce 'string'
let username = "alice";
// TypeScript deduce 'number'
let score = 100;
// TypeScript deduce 'boolean[]'
let flags = [true, false, true];
// TypeScript deduce tipul returnat ca 'number'
function add(a: number, b: number) {
return a + b;
}
Inferență pentru obiecte literale
TypeScript deduce că user are name, age și isAdmin. Citirea lui user.email, care nu a fost niciodată definit, este o eroare de compilare.
user cu name: "Alice", age: 30 și isAdmin: true, afișează user.name (corect), apoi afișează user.email — acea linie nu trebuie să compileze, cu eroarea "Property 'email' does not exist".
Ieșire: program TypeScript și rezultatul capturat
// TypeScript deduce forma obiectului
const user = {
name: "Alice",
age: 30,
isAdmin: true
};
// TypeScript știe că aceste proprietăți există
console.log(user.name); // OK
console.log(user.email); // Eroare: Property 'email' does not exist
Siguranța tipurilor în acțiune
Unul dintre principalele avantaje ale TypeScript este detectarea erorilor legate de tipuri încă din momentul în care scrii codul.
Să vedem cum ajută TypeScript la prevenirea greșelilor frecvente.
Erori de nepotrivire de tip — odată ce o variabilă are un tip, explicit sau dedus, atribuirea unei valori de alt tip este o eroare.
JavaScript față de TypeScript — în JavaScript, codul din fragmentul de mai jos rulează fără erori, dar poate provoca defecte: adunarea unui șir cu un număr le unește în șirul „53”. TypeScript detectează asta la compilare.
Nepotrivire de tip explicită
username este declarată ca string, așa că atribuirea numărului 42 este o eroare.
username ca string cu valoarea "alice", apoi atribuie-i numărul 42 — compilatorul trebuie să raporteze "Type 'number' is not assignable to type 'string'".
Ieșire: program TypeScript și rezultatul capturat
let username: string = "alice";
username = 42; // Eroare: Type 'number' is not assignable to type 'string'
Nepotrivire de tip implicită
score a fost dedusă ca number, așa că atribuirea șirului "high" este o eroare.
score = 100 (dedus number), apoi atribuie-i șirul "high" — compilatorul trebuie să raporteze "Type 'string' is not assignable to type 'number'".
Ieșire: program TypeScript și rezultatul capturat
let score = 100; // TypeScript deduce 'number'
score = "high"; // Eroare: Type 'string' is not assignable to type 'number'
Siguranța tipurilor în TypeScript
Cu parametri de tip number, apelul add("5", 3) este respins înainte ca acel cod să ruleze vreodată.
add(a: number, b: number): number care returnează a + b, apoi afișează add("5", 3) — apelul nu trebuie să compileze, cu eroarea "Argument of type 'string' is not assignable to parameter of type 'number'".
Ieșire: program TypeScript și rezultatul capturat
function add(a: number, b: number): number {
return a + b;
}
console.log(add("5", 3)); // Eroare: Argument of type 'string' is not assignable to parameter of type 'number'
Funcția add fără tipuri în JavaScript
Fără tipuri, add("5", 3) returnează în tăcere șirul "53" în loc de un număr.
// This is valid JavaScript but can lead to bugs
function add(a, b) {
return a + b;
}
console.log(add("5", 3)); // Returns "53" (string concatenation)
Când TypeScript nu poate deduce tipurile
Inferența din TypeScript este puternică, dar uneori nu poate determina tipul corect.
În acele cazuri TypeScript recurge la tipul any, care dezactivează verificarea tipurilor pentru acea valoare.
Notă: any și celelalte tipuri speciale sunt tratate mai în detaliu în capitolul următor.
Evită any când este posibil
Folosirea lui any dezactivează verificarea tipurilor din TypeScript.
În schimb, ia în considerare aceste alternative:
- Folosește adnotări de tip
- Creează interfețe pentru obiecte complexe
- Folosește gărzi de tip pentru verificarea tipurilor la rulare
- Activează
noImplicitAnyîntsconfig.json
Cazuri frecvente pentru any
JSON.parse returnează any pentru că structura nu este cunoscută la compilare, iar o variabilă declarată fără valoare este tot any — așa că acceptă mai întâi un șir și apoi un număr, fără să se plângă.
any.
Mai întâi, o constantă data obținută din JSON.parse('{ "name": "Alice", "age": 30 }'); apoi o variabilă something declarată fără valoare inițială, căreia i se atribuie mai întâi șirul 'salut' și apoi numărul 42, fără nicio eroare. Comentează fiecare caz și nu afișa nimic.
Ieșire: program TypeScript și rezultatul capturat
// 1. JSON.parse returnează 'any' pentru că structura nu este cunoscută la compilare
const data = JSON.parse('{ "name": "Alice", "age": 30 }');
// 2. Variabile declarate fără inițializare
let something; // Tipul este 'any'
something = 'salut';
something = 42; // Nicio eroare