composite în TypeScript

Pregătește un proiect pentru a fi folosit prin „references” de alte proiecte și construit cu tsc -b.

Sintaxă
"compilerOptions": { "composite": true },
"references": [{ "path": "../utile" }]

tsc -b
tsc --build --verbose

Ce face composite

Proiectele mari (monorepo-uri) se împart în mai multe proiecte TypeScript mici, legate prin "references" în tsconfig.json. Un proiect referit trebuie să aibă composite: true (altfel TS6306). Opțiunea pornește automat declaration și incremental și cere ca toate fișierele să fie în files/include (TS6307), ca tsc să știe exact ce aparține fiecărui proiect.

Proiectele se construiesc cu tsc -b (--build), care compilează în ordinea corectă doar proiectele schimbate. Cu --verbose explică ce face; --clean șterge fișierele generate; --force reconstruiește tot. Când un proiect se schimbă, dar fișierele lui .d.ts rămân la fel, proiectele care depind de el nu mai sunt verificate din nou. Implicit: false.

Parametri

Parametru Descriere
true Proiectul poate fi referit și construit cu tsc -b.
false Valoarea implicită.

Exemple

Exemplul 1: Două proiecte construite cu tsc -b

app folosește utile. La prima rulare se construiesc amândouă, în ordine, iar programul rulează. După o modificare în utile care nu schimbă tipurile (fișierul .d.ts rămâne la fel), doar utile este reconstruit.

// tsconfig.json (rădăcina)
{
  "files": [],
  "references": [{ "path": "./utile" }, { "path": "./app" }]
}

// utile/tsconfig.json
{
  "compilerOptions": {
    "module": "nodenext",
    "target": "es2022",
    "composite": true,
    "outDir": "../dist/utile"
  }
}

// app/tsconfig.json
{
  "compilerOptions": {
    "module": "nodenext",
    "target": "es2022",
    "composite": true,
    "outDir": "../dist/app"
  },
  "references": [{ "path": "../utile" }]
}

// utile/calcul.ts
export function cuTva(pret: number): number {
  return Math.round(pret * 1.19 * 100) / 100;
}

// app/index.ts
import { cuTva } from "../utile/calcul.js";

console.log(cuTva(100));

Rezultat (ora diferă la fiecare rulare)

$ npx tsc -b --verbose
7:57:18 PM - Projects in this build: 
    * utile/tsconfig.json
    * app/tsconfig.json
    * tsconfig.json

7:57:18 PM - Project 'utile/tsconfig.json' is out of date because output file 'dist/utile/tsconfig.tsbuildinfo' does not exist

7:57:18 PM - Building project '/proiect/utile/tsconfig.json'...

7:57:19 PM - Project 'app/tsconfig.json' is out of date because output file 'dist/app/tsconfig.tsbuildinfo' does not exist

7:57:19 PM - Building project '/proiect/app/tsconfig.json'...

$ find dist -type f | sort
dist/app/index.d.ts
dist/app/index.js
dist/app/tsconfig.tsbuildinfo
dist/utile/calcul.d.ts
dist/utile/calcul.js
dist/utile/tsconfig.tsbuildinfo

$ node dist/app/index.js
119

$ npx tsc -b --verbose        # după o modificare în utile/calcul.ts
7:57:20 PM - Projects in this build: 
    * utile/tsconfig.json
    * app/tsconfig.json
    * tsconfig.json

7:57:20 PM - Project 'utile/tsconfig.json' is out of date because output 'dist/utile/tsconfig.tsbuildinfo' is older than input 'utile/calcul.ts'

7:57:20 PM - Building project '/proiect/utile/tsconfig.json'...

7:57:20 PM - Project 'app/tsconfig.json' is up to date with .d.ts files from its dependencies

7:57:20 PM - Updating output timestamps of project '/proiect/app/tsconfig.json'...

Exemplul 2: Erorile cerute de composite

Primul rezultat: app referă un proiect fără composite. Al doilea: un proiect composite cu "files": ["index.ts"] importă un fișier care nu este în listă.

// utile/tsconfig.json fără "composite": true
// sau
// tsconfig.json cu "composite": true și "files": ["index.ts"]

Rezultat (tsc 5.9)

$ npx tsc -p app
app/tsconfig.json(7,18): error TS6306: Referenced project '/proiect/utile' must have setting "composite": true.

$ npx tsc
index.ts(1,19): error TS6307: File '/proiect/alt.ts' is not listed within the file list of project '/proiect/tsconfig.json'. Projects must list all files or use an 'include' pattern.
  File is ECMAScript module because '/proiect/package.json' has field "type" with value "module"

Greșeli frecvente

  • Să rulezi tsc -p app în loc de tsc -b. -p nu construiește proiectele referite; dacă fișierele lor .d.ts lipsesc, apar erori.
  • Să folosești noEmit într-un proiect referit. Proiectele care depind de el au nevoie de fișierele lui .d.ts.

Comenzi înrudite

  • incremental: Salvează informații despre ultima compilare într-un fișier .tsbuildinfo, ca următoarea compilare să refacă doar ce s-a schimbat.
  • declaration: Generează lângă fiecare fișier .js un fișier .d.ts cu tipurile lui, ca alte proiecte să-l poată folosi cu tipuri.
  • disableSourceOfProjectReferenceRedirect: Trei opțiuni pentru editor în proiectele cu references: cum se încarcă proiectele referite, ca editorul să fie mai rapid.
  • --project: Compilează proiectul descris de un anumit fișier tsconfig (sau de tsconfig.json dintr-un director dat).
  • rootDir: Spune care director este rădăcina surselor; structura de sub el se păstrează în outDir.