Treci la conținutul principal

TypeScript în proiecte JavaScript (JSDoc)

Comentariile JSDoc îți permit să adaugi verificarea de tipuri TypeScript în fișiere JavaScript obișnuite, fără să le redenumești în .ts.

Este ideal atunci când vrei să migrezi un proiect pas cu pas sau când vrei pur și simplu siguranța tipurilor într-un cod JavaScript.

Notă: exemplele de pe această pagină sunt scrise ca JavaScript cu tipuri JSDoc. Salvează-le ca fișiere .js cu // @ts-check la început (sau cu checkJs activat) ca să vezi verificarea de tipuri descrisă. Într-un fișier .ts compilatorul ignoră tipurile JSDoc și se bazează în schimb pe adnotările obișnuite.


Primii pași

Ca TypeScript să îți verifice fișierele JavaScript trebuie:

  1. Să creezi un fișier tsconfig.json (dacă nu ai deja unul)
  2. Să activezi checkJs în el sau să pui // @ts-check la începutul fiecărui fișier pe care vrei să îl verifici

Exemplu: JSDoc pentru siguranța tipurilor

Un comentariu JSDoc scris deasupra funcției îi spune lui TypeScript că atât parametrii, cât și valoarea returnată sunt numere.

Prompt
Arată cea mai mică funcție cu tipuri JSDoc, având // @ts-check activat la începutul fișierului. Scrie o funcție add(a, b) documentată cu @param {number} a, @param {number} b și @returns {number}, care returnează suma. Este nevoie doar de declarație — programul nu afișează nimic.
Ieșire: program TypeScript și rezultatul capturat

Obiecte și interfețe

Poți descrie forma unui obiect direct într-o etichetă JSDoc sau îi poți da un nume cu @typedef, astfel încât tipul să poată fi refolosit în mai multe locuri.

Tipuri de obiect inline

Tipul parametrului este scris pe loc, ca tip de obiect literal. Într-un fișier .js verificat, apelarea lui greet fără lastName este raportată ca eroare.

Prompt
Arată un tip de obiect scris direct (inline) în JSDoc pentru un parametru de funcție. Cu // @ts-check activat, documentează greet(person) cu @param {{ firstName: string, lastName: string, age?: number }} person și returnează Salut, <firstName> <lastName>. Apeleaz-o o dată cu un obiect complet (John Doe) și o dată doar cu firstName: "Jane", marcând al doilea apel cu un comentariu ca fiind eroarea de lastName lipsă pe care o raportează un fișier .js verificat. Nu se afișează nimic.
Ieșire: program TypeScript și rezultatul capturat

Folosirea lui @typedef pentru tipuri complexe

@typedef împreună cu liniile @property definesc un tip numit User. Parantezele drepte marchează o proprietate opțională, iar o uniune scrisă între paranteze rotunde limitează role la câteva valori.

Prompt
Arată etichetele @typedef și @property care descriu un tip de obiect în JSDoc. Definește un typedef User cu id: number, username: string, email opțional, un role limitat la "admin" | "user" | "guest" și o metodă getFullName care returnează un șir de caractere. Declară currentUser cu /** @type {User} */ (id 1, username johndoe, role admin, getFullName() returnând John Doe) și afișează currentUser.role.
Ieșire: program TypeScript și rezultatul capturat

Extinderea tipurilor

O intersecție (Point & { z: number }) construiește un tip nou pornind de la unul existent. Într-un fișier .js verificat, obiectul fără z este o eroare, exact cea pe care o așteaptă comentariul @ts-expect-error. Compilat ca fișier .ts, tipurile JSDoc sunt ignorate, așa că în schimb compilatorul raportează directiva ca nefolosită.

Prompt
Arată cum un typedef JSDoc poate extinde altul printr-un tip intersecție. Definește Point ca { x: number, y: number } și Point3D ca Point & { z: number }. Declară point3d cu tipul Point3D, având x 1, y 2, z 3, apoi un obiect point2d fără z, precedat de un comentariu // @ts-expect-error - proprietatea z lipsește. Într-un fișier .js cu // @ts-check, lipsa lui z este eroarea așteptată; într-un fișier .ts tipurile JSDoc sunt ignorate, așa că în schimb compilatorul raportează directiva ca nefolosită.
Ieșire: program TypeScript și rezultatul capturat

Tipuri de funcție

JSDoc poate descrie fiecare parte a unei funcții: parametrii ei, valoarea returnată, tipurile de callback și chiar mai multe semnături supraîncărcate.

Declarații de funcții

Fiecare @param dă unui parametru un tip și o scurtă descriere; @returns face același lucru pentru rezultat.

Prompt
Arată o declarație de funcție documentată complet, cu tipuri JSDoc pentru parametri și pentru valoarea returnată. Cu // @ts-check activat, scrie calculateArea(width, height) documentată cu @param {number} pentru ambii parametri (cu scurte descrieri) și @returns {number} Aria calculată, care returnează produsul. Pune calculateArea(10, 20) în area. Nu se afișează nimic.
Ieșire: program TypeScript și rezultatul capturat

Expresii de funcție și callback-uri

@callback definește un tip de funcție reutilizabil. Acesta poate fi folosit apoi cu @type pe o funcție săgeată sau ca tip de parametru.

Prompt
Arată @callback pentru a tipiza expresii de funcție și parametri de tip callback în JSDoc. Definește un tip de callback StringProcessor care primește un string și returnează un string. Declară toUpperCase cu @type {StringProcessor} ca funcție săgeată, apoi processStrings(strings, processor) documentată cu @param {string[]}, @param {StringProcessor} și @returns {string[]}, care trece tabloul prin processor folosind map. Apeleaz-o cu ["salut", "lume"] și toUpperCase. Nu se afișează nimic.
Ieșire: program TypeScript și rezultatul capturat

Supraîncărcarea funcțiilor

Mai multe blocuri @overload dau unei singure funcții mai multe semnături. Ultimul bloc descrie implementarea care le tratează pe toate.

Prompt
Arată etichetele JSDoc @overload care dau unei singure funcții două semnături tipizate. Scrie add(a, b) cu două blocuri @overload — string plus string returnează string, number plus number returnează number — urmate de semnătura de implementare string | number. Dacă oricare dintre argumente este un string, returnează concatenarea prin String(), altfel suma numerică. Apeleaz-o ca add("Salut, ", "Lume!") și add(10, 20). Nu se afișează nimic.
Ieșire: program TypeScript și rezultatul capturat

Tipuri avansate

Funcționalități TypeScript mai avansate — uniuni, intersecții, generice, tipuri mapate și condiționale — sunt disponibile și prin JSDoc.

Tipuri uniune și intersecție

& combină tipuri, iar | permite unul dintre mai multe tipuri. O verificare cu in restrânge o uniune în interiorul unei funcții.

Prompt
Arată tipuri uniune și intersecție construite cu @typedef din JSDoc. Definește Person (name, age), Employee ca Person & { employeeId: string } și Visitor ca Person | { guestId: string, visitDate: Date }. Declară un employee (Alice, 30, E123) și un guest (G456, new Date()), apoi getVisitorId(visitor), care folosește o verificare "guestId" in visitor pentru a returna fie guestId, fie name. Nu se afișează nimic.
Ieșire: program TypeScript și rezultatul capturat

Tipuri mapate și condiționale

@template face un typedef generic. Corpul typedef-ului poate folosi apoi tipuri mapate, redenumirea cheilor și tipuri condiționale, exact ca într-un fișier .ts.

Prompt
Arată că typedef-urile JSDoc cu @template pot exprima tipuri mapate și condiționale. Definește un typedef generic MethodNames<T> care păstrează doar cheile lui T ale căror valori sunt funcții, și un tip mapat generic Getters<T> care redenumește fiecare cheie K în `get${Capitalize<K>}`, returnând () => T[K]. Declară userGetters cu tipul Getters<{ name: string, age: number }>, unde getName returnează "John" și getAge returnează 30, și citește ambele valori în name și age. Adaugă export {} pentru ca name să nu intre în conflict cu variabila globală. Nu se afișează nimic.
Ieșire: program TypeScript și rezultatul capturat

Importul tipurilor

Un tip JSDoc poate fi importat din alt fișier sau dintr-un pachet cu import('...') în interiorul unui @typedef. Pentru bibliotecile care nu vin cu tipuri, îți poți scrie propriul fișier de declarații (.d.ts).

Importul tipurilor în JSDoc

Trei moduri de a aduce un tip într-un fișier JavaScript: dintr-un fișier TypeScript local, dintr-un pachet din node_modules și cu un nume nou.

script.ts
// @ts-check

// Importing types from TypeScript files
/** @typedef {import('./types').User} User */

// Importing types from node_modules
/** @typedef {import('express').Request} ExpressRequest */

// Importing with renaming
/** @typedef {import('./api').default as ApiClient} ApiClient */

Fișier de declarații pentru un modul

Un fișier types.d.ts care declară pachetul my-module: o interfață Config și două funcții exportate.

script.ts
// types.d.ts
declare module 'my-module' {
  export interface Config {
    apiKey: string;
    timeout?: number;
    retries?: number;
  }

  export function initialize(config: Config): void;
  export function fetchData<T = any>(url: string): Promise<T>;
}

Bune practici

Urmează aceste practici când folosești JSDoc împreună cu TypeScript:

  • Pune // @ts-check la începutul fiecărui fișier pe care vrei să îl verifici
  • Folosește @typedef pentru tipurile complexe care apar în mai multe locuri
  • Documentează toți parametrii funcțiilor și tipurile returnate
  • Folosește @template pentru funcții și tipuri generice
  • Scrie fișiere de declarații (.d.ts) pentru bibliotecile externe fără tipuri
  • Preferă @ts-expect-error în locul lui @ts-ignore atunci când te aștepți la o eroare

Capcane frecvente

Ai grijă la aceste probleme frecvente:

  • Lipsa lui // @ts-check: fără el (sau fără checkJs) nu se verifică nimic
  • Sintaxă JSDoc incorectă: o singură greșeală de scriere poate opri verificarea de tipuri pentru acel comentariu
  • Conflicte de tipuri: tipurile din surse diferite pot să nu se potrivească
  • Probleme de inferență: uneori TypeScript nu poate deduce singur un tip
  • Performanță: fișierele JavaScript mari, cu tipuri complexe, pot fi verificate încet

Concluzie

JSDoc împreună cu TypeScript este un mod puternic de a adăuga siguranța tipurilor într-un proiect JavaScript, fără a converti fișierele în TypeScript.

Este util în special pentru:

  • Migrarea treptată a unui cod JavaScript către TypeScript
  • Adăugarea verificării de tipuri într-un proiect JavaScript existent
  • Lucrul în medii în care fișierele .ts nu sunt acceptate
  • Documentarea codului JavaScript cu informații despre tipuri

Cu tiparele de pe această pagină obții multe dintre beneficiile TypeScript, continuând totuși să scrii JavaScript.

Ține minte: pentru proiecte noi sau pentru migrări complete, fișierele .ts oferă în continuare cea mai bună experiență TypeScript.

Ești gata să începi? Adaugă // @ts-check în fișierele tale JavaScript și începe să adaugi adnotări de tip JSDoc. Compilatorul va prinde erorile înainte ca ele să ajungă în producție.