Treci la conținutul principal

Ghid de migrare la TypeScript

Mutarea unui proiect JavaScript la TypeScript face codul mai ușor de întreținut și îți oferă o experiență de editare mult mai bună.

Acest ghid te conduce pas cu pas prin migrare.


Etapa de pregătire

Evaluează baza de cod. Înainte de a începe migrarea:

  • Stabilește dimensiunea și complexitatea bazei de cod
  • Documentează procesul de construire și dependențele
  • Caută definiții de tip existente (fișiere .d.ts)
  • Identifică traseele critice care au nevoie de atenție suplimentară

Pregătește controlul versiunilor. Asigură-te că ai un depozit git curat (sau echivalent). Creează o ramură pentru migrare și înregistrează starea curentă, ca să poți oricând compara sau reveni:

  • git checkout -b typescript-migration
  • git add .
  • git commit -m "Pre-TypeScript migration state"

Configurare

Instalează TypeScript ca dependență de dezvoltare, împreună cu definițiile de tip pentru Node.js: npm install --save-dev typescript @types/node

Creează tsconfig.json. Pornește de la o configurație de bază în rădăcina proiectului:

  • "compilerOptions": {
  • "target": "ES2020",
  • "module": "commonjs",
  • "strict": true,
  • "esModuleInterop": true,
  • "skipLibCheck": true,
  • "forceConsistentCasingInFileNames": true,
  • "outDir": "./dist",
  • "rootDir": "./src"
  • },
  • "include": ["src/**/*"],
  • "exclude": ["node_modules"]

Notă: ajustează target la cel mai vechi mediu pe care trebuie să îl susții.


Abordări de migrare

Există două moduri de a migra.

Migrare graduală. Convertește câte un fișier pe rând, în timp ce restul rămâne JavaScript. Activează "allowJs": true și "checkJs": true în compilerOptions, astfel încât compilatorul să accepte și să verifice fișierele .js alături de fișierele .ts. Cea mai bună variantă pentru baze de cod mari, unde vrei perturbări minime.

Migrare dintr-o dată. Redenumește fiecare fișier .js în .ts și corectează erorile, de exemplu cu find src -name "*.js" -exec sh -c 'mv "$0" "${0%.js}.ts"' {} \;. Cea mai bună variantă pentru proiecte mici și medii și pentru proiecte noi (greenfield).

Notă: pentru proiectele mari este recomandată cu tărie abordarea graduală — menține perturbările reduse și volumul de muncă ușor de gestionat.


Migrare pas cu pas

1. Începe cu configurarea. Creează un tsconfig.json cu aceste setări recomandate, care îi permit lui TypeScript să îți verifice codul JavaScript fără a genera încă fișiere:

  • "compilerOptions": {
  • "target": "ES2020",
  • "module": "commonjs",
  • "strict": true,
  • "esModuleInterop": true,
  • "skipLibCheck": true,
  • "forceConsistentCasingInFileNames": true,
  • "outDir": "./dist",
  • "rootDir": "./src",
  • "allowJs": true,
  • "checkJs": true,
  • "noEmit": true
  • },
  • "include": ["src/**/*"],
  • "exclude": ["node_modules", "dist"]

2. Activează verificarea de tip pentru JavaScript. Adaugă // @ts-check la începutul unui fișier JavaScript și TypeScript începe să îl verifice (vezi primul fragment). Poți reduce la tăcere o singură linie cu // @ts-ignore.

3. Redenumește fișierele în .ts. Începe cu fișierele necritice. Redenumește un fișier cu mv src/utils/helpers.js src/utils/helpers.ts sau un director întreg (cu grijă) cu find src/utils -name "*.js" -exec sh -c 'mv "$0" "${0%.js}.ts"' {} \;.

4. Adaugă adnotări de tip. Dă treptat tipuri parametrilor, valorilor returnate și obiectelor (vezi al doilea fragment).

5. Actualizează scripturile de construire și de testare. Adaugă compilarea TypeScript în package.json: "scripts": { "build": "tsc", "dev": "tsc --watch", "test": "jest" }. Asigură-te că și configurația de teste poate rula fișiere TypeScript.

Verificarea de tip a unui fișier JavaScript

Cu // @ts-check și un tip JSDoc, atribuirea unui număr lui name este raportată ca eroare.

script.ts
// @ts-check

/** @type {string} */
const name = 'John';

// TypeScript will catch this error
name = 42; // Error: Type '42' is not assignable to type 'string'

Adăugarea adnotărilor de tip

Aceeași funcție add înainte și după tipizare, plus o interfață folosită ca tip returnat.

script.ts
// Before
function add(a, b) {
  return a + b;
}

// After
function add(a: number, b: number): number {
  return a + b;
}

// With interface
interface User {
  id: number;
  name: string;
  email?: string;
}

function getUser(id: number): User {
  return { id, name: 'John Doe' };
}

Unelte de migrare

Unele unelte pot face o parte din muncă în locul tău:

  • ts-migrate — o unealtă automată de migrare de la JavaScript la TypeScript: npx ts-migrate-full . (depozit GitHub)
  • TypeStat — convertește JavaScript în TypeScript cu siguranță de tip: npx typestat (depozit GitHub)
  • pachetele @types — definiții de tip pentru dependențele tale, de exemplu npm install --save-dev @types/react @types/node (caută-le pe TypeSearch)

Bune practici pentru migrarea la TypeScript

Începe cu pași mici și iterează

  • Începe cu funcțiile utilitare și cu componentele care nu țin de interfața grafică
  • Migrează câte un fișier sau un modul pe rând
  • Înregistrează o comitere după fiecare pas reușit

Folosește facilitățile TypeScript — lasă inferența să lucreze acolo unde poate, folosește tipuri uniune pentru flexibilitate și gărzi de tip pentru verificări la execuție (vezi fragmentul).

Descurcă-te cu bibliotecile terțe

  • Instalează pachetele @types pentru dependențele tale
  • Scrie fișiere de declarații pentru bibliotecile care nu au tipuri
  • Folosește declare module pentru extinderi globale de tip

Facilități utile din TypeScript

Inferența de tip, un alias de tip uniune și o funcție gardă de tip — trei facilități care fac codul migrat mai sigur cu efort minim.

script.ts
// Use type inference where possible
const name = 'John';  // TypeScript infers 'string'
const age = 30;       // TypeScript infers 'number'

// Use union types for flexibility
type Status = 'active' | 'inactive' | 'pending';

// Use type guards for runtime checks
function isString(value: any): value is string {
  return typeof value === 'string';
}

Provocări frecvente și soluții

Proprietăți dinamice

Problemă: JavaScript folosește adesea obiecte simple pe post de dicționare, adăugând proprietăți mai târziu. TypeScript raportează că proprietatea nu există.

Soluție: folosește o semnătură de index sau o aserțiune de tip.

Gestionarea contextului this

Problemă: this se pierde în interiorul unei funcții callback obișnuite.

Soluție: folosește o funcție săgeată sau leagă explicit this.

Proprietăți dinamice: problema

Adăugarea proprietății name la un literal de obiect gol este o eroare, deoarece tipul lui nu are o astfel de proprietate.

script.ts
// Before
const user = {};
user.name = 'John';  // Error: Property 'name' does not exist

Proprietăți dinamice: soluția

Fie o interfață cu o semnătură de index, fie o aserțiune de tip permite adăugarea proprietății.

script.ts
// Option 1: Index signature
interface User {
  [key: string]: any;
}
const user: User = {};
user.name = 'John';  // OK

// Option 2: Type assertion
const user = {} as { name: string };
user.name = 'John';  // OK

Contextul this: problema

În interiorul unui callback function obișnuit transmis lui setTimeout, this nu mai este instanța Counter.

script.ts
class Counter {
  count = 0;
  increment() {
    setTimeout(function() {
      this.count++;  // Error: 'this' is not defined
    }, 1000);
  }
}

Contextul this: soluția

O funcție săgeată păstrează this din contextul înconjurător; alternativ, tipizează this ca Counter și apelează .bind(this).

script.ts
// Solution 1: Arrow function
setTimeout(() => {
  this.count++;  // 'this' is lexically scoped
}, 1000);

// Solution 2: Bind 'this'
setTimeout(function(this: Counter) {
  this.count++;
}.bind(this), 1000);

Concluzie

Migrarea de la JavaScript la TypeScript este o investiție mare, dar care merită, în baza ta de cod. Cu acest ghid poți face schimbarea lin și treptat.

Idei principale:

  • Începe cu un tsconfig.json solid
  • Folosește allowJs și checkJs pentru o migrare graduală
  • Lasă sistemul de tipuri să prindă erorile devreme
  • Actualizează procesul de construire și de testare ca să susțină TypeScript
  • Rezolvă provocările frecvente cu tiparele arătate mai sus

Migrarea este un proces, nu un eveniment. O bază de cod mixtă în timpul tranziției este în regulă — contează progresul constant, păstrând calitatea codului ridicată.

Gata de început? Pregătește TypeScript în proiectul tău și adaugă treptat adnotări de tip; compilatorul te va îndruma către un cod mai robust. Pentru mai multe informații, vezi ghidul oficial de migrare TypeScript.