JSDoc cu tipuri în TypeScript

Tipuri scrise în comentarii JSDoc, ca TypeScript să verifice fișiere JavaScript fără să le transformi în .ts.

Sintaxă
// @ts-check
/** @param {number} a @returns {number} */
function f(a) { ... }
/** @typedef {{ nume: string }} Elev */
/** @type {Elev[]} */

Ce face JSDoc cu tipuri

TypeScript poate verifica și fișiere .js. Tipurile se scriu în comentarii JSDoc (/** ... */): @param {number} pret, @returns {string}, @type {Elev[]}, @typedef pentru a defini un tip nou, @template T pentru generics, @import pentru a importa tipuri. Codul rămâne JavaScript valid și rulează fără compilare.

Verificarea se pornește cu // @ts-check la începutul fișierului sau, pentru tot proiectul, cu opțiunile allowJs și checkJs. Editorul (VS Code) folosește aceste tipuri pentru completare chiar și fără verificare. Este o cale bună de a introduce TypeScript treptat într-un proiect JavaScript.

În fișierele .ts, JSDoc nu dă tipuri (tipurile se scriu în cod), dar descrierile, @deprecated și @example apar în editor când treci cu mouse-ul peste funcție.

Exemple

Exemplul 1: Fișier JavaScript verificat cu @ts-check

Al doilea produs are prețul scris ca text. Comanda tsc --allowJs --checkJs --noEmit calcul.js găsește greșeala.

// calcul.js
// @ts-check

/**
 * @typedef {Object} Produs
 * @property {string} nume
 * @property {number} pret
 */

/**
 * Totalul coșului, în lei.
 * @param {Produs[]} produse
 * @returns {number}
 */
export function total(produse) {
    return produse.reduce((s, p) => s + p.pret, 0);
}

console.log(total([{ nume: "Pâine", pret: 5 }, { nume: "Lapte", pret: "7.5" }]));

Eroarea afișată de tsc

calcul.js(18,65): error TS2322: Type 'string' is not assignable to type 'number'.

Exemplul 2: Același fișier rulat direct cu node

JavaScript nu verifică tipurile: 5 + "7.5" lipește textele și dă "57.5". Exact greșeala pe care @ts-check a prins-o.

node calcul.js

Rezultat (rulat cu node)

57.5

Exemplul 3: JSDoc într-un fișier TypeScript

Aici tipurile sunt în cod; JSDoc adaugă doar documentație, vizibilă în editor.

/**
 * Calculează media notelor, rotunjită la două zecimale.
 * @param note Notele elevului, între 1 și 10.
 * @example media([9, 10]) // 9.5
 */
function media(note: number[]): number {
    return Math.round((note.reduce((s, n) => s + n, 0) / note.length) * 100) / 100;
}

/** @deprecated Folosește {@link media}. */
function medie(note: number[]): number {
    return media(note);
}

console.log(media([9, 10]), medie([7, 8, 10]));

Rezultat

9.5 8.33

Greșeli frecvente

  • Scrii comentariul cu o singură steluță (/* @param ... */). JSDoc începe cu /**; altfel este ignorat.
  • Pui tipuri JSDoc într-un fișier .ts și te aștepți să fie folosite. În TypeScript contează doar tipurile din cod.

Comenzi înrudite

  • @ts-ignore și @ts-expect-error: Comentarii care opresc raportarea erorii de pe linia următoare; @ts-expect-error cere ca eroarea să existe.
  • fișiere .d.ts: Fișiere care conțin doar tipuri: descriu codul JavaScript ca să poată fi folosit din TypeScript cu verificare.
  • import type: Importă doar tipuri; importul dispare complet din JavaScript-ul generat.
  • checkJs: Raportează erorile de tip și în fișierele .js, folosind tipurile deduse și comentariile JSDoc.
  • allowJs: Permite fișiere .js în proiectul TypeScript: pot fi importate din .ts, sunt copiate în outDir și au tipuri deduse.