Menu

tsconfig.json: opzioni, valori predefiniti ed esempi

tsconfig.json indica che una cartella è un progetto TypeScript e imposta le opzioni del compilatore. Le opzioni che contano (target, module, moduleResolution, strict, rootDir, outDir, include, lib, types, noEmit, skipLibCheck), una configurazione iniziale consigliata, extends e cosa è cambiato in TypeScript 7.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

tsconfig.json è il file di configurazione di un progetto TypeScript. Quando esegui tsc senza argomenti, il compilatore lo cerca nella cartella corrente (poi nelle cartelle superiori), legge le opzioni in compilerOptions e controlla i file elencati da include. Eccone uno piccolo ma completo:

{
    "compilerOptions": {
        "target": "es2022",
        "module": "nodenext",
        "strict": true,
        "rootDir": "./src",
        "outDir": "./dist"
    },
    "include": ["src"]
}

Questo compila ogni file TypeScript in src in JavaScript dentro dist, come codice ES2022, con le regole dei moduli di Node.js e tutti i controlli strict attivi. npx tsc --init genera un file iniziale più lungo, con un commento su ogni opzione.

Il file è JSON con commenti: sono accettati i commenti //, i commenti /* */ e le virgole finali.

Una configurazione iniziale consigliata

Per un'applicazione o uno script Node.js:

{
    "compilerOptions": {
        "rootDir": "./src",
        "outDir": "./dist",

        "target": "es2024",
        "lib": ["es2024"],
        "module": "nodenext",
        "types": ["node"],

        "strict": true,
        "noUncheckedIndexedAccess": true,
        "verbatimModuleSyntax": true,
        "skipLibCheck": true,
        "sourceMap": true
    },
    "include": ["src"]
}

Serve npm install --save-dev @types/node per i tipi di Node.js. Con module: "nodenext", il campo "type" in package.json decide se un file .ts è un modulo ES ("type": "module") o CommonJS ("type": "commonjs", che è ciò che scrive npm init -y). Usa "type": "module" per i nuovi progetti che usano import ed export.

Per il codice costruito da un bundler come Vite, esbuild o webpack, è il bundler a scrivere il JavaScript e tsc si limita a controllare:

{
    "compilerOptions": {
        "target": "es2022",
        "lib": ["es2022", "dom"],
        "module": "preserve",
        "noEmit": true,

        "strict": true,
        "noUncheckedIndexedAccess": true,
        "verbatimModuleSyntax": true,
        "isolatedModules": true,
        "skipLibCheck": true,
        "jsx": "react-jsx"
    },
    "include": ["src"]
}

I template dei framework (Vite, Next.js, Angular) generano il proprio tsconfig.json. Parti dal loro invece di sostituirlo.

Le opzioni che contano

OpzioneCosa faValore predefinito in TypeScript 7
targetVersione di JavaScript dell'output; la sintassi più recente viene riscritta per i target più vecchies2025
libTipi delle API integrate che il checker conosce (Array.prototype.at, Map, document)Segue target, più il DOM
moduleTipo di codice di modulo emesso e regole dei moduli applicateesnext
moduleResolutionCome vengono trovati sul disco i percorsi di importnodenext o node16 con il module corrispondente, altrimenti bundler
strictAttiva l'intera famiglia di controlli stricttrue
rootDirCartella la cui struttura viene riprodotta in outDirLa cartella che contiene tsconfig.json
outDirDove finiscono i file .js (e .d.ts)Accanto a ogni file sorgente
include / exclude / filesQuali file fanno parte del progettoOgni file .ts nella cartella
typesQuali pacchetti @types vengono caricati senza import[], nessuno
noEmitSolo controllo, non scrive nullafalse
declarationScrive anche i file di dichiarazione dei tipi .d.tsfalse
sourceMapScrive file .js.map per i debuggerfalse
esModuleInteropFa funzionare import x from "cjs-package" con i pacchetti CommonJStrue (non si può disattivare)
skipLibCheckSalta il controllo dei tipi dei file .d.ts, compresi quelli in node_modulesfalse

target e lib

target dice su quale versione di JavaScript deve girare l'output. La sintassi più recente del target viene riscritta: con "target": "es2017", un campo di classe o ??= diventa codice più vecchio. Il target più basso che TypeScript 7 accetta è es2015 (es6); es5 è stato rimosso.

target non aggiunge le API di runtime mancanti. Descriverle è compito di lib, fornirle è compito di un polyfill. lib dice al checker quali oggetti e metodi integrati esistono. Il suo valore predefinito segue target e include anche i tipi DOM del browser, quindi document supera il controllo dei tipi anche in un progetto Node.js, a meno che tu non imposti lib. Usare un metodo di uno standard più recente della tua lib è un errore di compilazione:

src/b.ts(1,24): error TS2550: Property 'toSorted' does not exist on type 'number[]'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2023' or later.

Gli esempi eseguibili di questa documentazione usano la lib es2022, quindi toSorted, Object.groupBy e i nuovi metodi di Set non sono disponibili.

module e moduleResolution

module ha tre valori sensati per il codice nuovo:

  • nodenext: per il codice eseguito da Node.js. Ogni file è ESM o CommonJS in base alla sua estensione (.mts, .cts) o al "type" del package.json più vicino, esattamente come decide Node. Gli import relativi nei moduli ES richiedono un'estensione, scritta come .js anche se il sorgente è .ts: import { add } from "./math.js". moduleResolution si adegua in automatico.
  • preserve: per il codice elaborato da un bundler. Gli import restano come sono scritti e la risoluzione usa le regole bundler, che ammettono import senza estensione.
  • esnext: output come semplici moduli ES, con risoluzione bundler. È il valore predefinito quando module non è impostato.

Un primo errore frequente con la configurazione di tsc --init nasce dal fatto che npm init -y scrive "type": "commonjs":

src/main.ts(1,10): error TS1295: ECMAScript imports and exports cannot be written in a CommonJS file under 'verbatimModuleSyntax'.

Il file usa import, ma package.json dice che il progetto è CommonJS. Cambia "type" in "module". La pagina sui moduli tratta import ed export nel dettaglio.

strict e le opzioni di controllo

"strict": true attiva in un colpo solo un gruppo di controlli: noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, strictBuiltinIteratorReturn, noImplicitThis e useUnknownInCatchVariables. È il valore predefinito in TypeScript 7 ed è attivo in ogni esempio eseguibile di queste pagine. Il codice scritto per lo strict mode restringe il tipo prima di usare un valore che potrebbe mancare:

Senza un'annotazione, il tipo di un parametro non si può dedurre, e noImplicitAny lo segnala:

index.ts(2,17): error TS7006: Parameter 'n' implicitly has an 'any' type.

strict non include tutti i controlli utili. Due che vale la pena aggiungere sono noUncheckedIndexedAccess (un elemento di array o una lettura tramite index signature ha tipo T | undefined) e exactOptionalPropertyTypes (a una proprietà opzionale non si può assegnare esplicitamente undefined); tsc --init li attiva entrambi. I controlli di stile come noUnusedLocals, noImplicitReturns e noFallthroughCasesInSwitch sono disattivati di default.

Quali file: include, exclude, rootDir, outDir

Senza include o files, il progetto contiene ogni file .ts, .tsx e .d.ts della cartella e delle sue sottocartelle. node_modules resta sempre fuori. Anche outDir resta fuori, ma solo finché non imposti exclude: una lista exclude personalizzata sostituisce quella predefinita, quindi aggiungici la cartella di output. include ed exclude accettano pattern glob:

{
    "include": ["src", "scripts/**/*.ts"],
    "exclude": ["src/**/*.test.ts"]
}

exclude filtra solo ciò che include ha trovato. Un file importato da un altro file incluso viene comunque compilato.

outDir è dove va l'output, e rootDir è la parte dell'albero dei sorgenti che viene riprodotta al suo interno: con "rootDir": "./src", src/api/users.ts diventa dist/api/users.js. Impostali entrambi. rootDir vale di default la cartella che contiene tsconfig.json, quindi se imposti solo outDir mentre i sorgenti stanno in src, TypeScript 7 si ferma con:

error TS5011: The common source directory of 'tsconfig.json' is './src'. The 'rootDir' setting must be explicitly set to this or another path to adjust your output's file layout.

Opzioni di output: noEmit, declaration, sourceMap

  • "noEmit": true fa di tsc un puro type checker. Usalo quando un altro strumento (un bundler, tsx, il type stripping di Node.js) produce il JavaScript.
  • "declaration": true scrive un file .d.ts per modulo, i tipi senza il codice. Le librerie ne hanno bisogno perché i loro utenti ricevano i tipi. declarationMap aggiunge le mappe per il "vai alla definizione" verso il sorgente .ts.
  • "sourceMap": true scrive i file .js.map, così debugger e stack trace puntano alle righe del .ts.
  • "noEmitOnError": true non scrive nulla finché ci sono errori di tipo. Senza questa opzione, tsc segnala gli errori e scrive comunque il JavaScript.

types, esModuleInterop e skipLibCheck

types elenca i pacchetti @types caricati globalmente, senza import. Il valore predefinito di TypeScript 7 è una lista vuota, quindi dopo npm install --save-dev @types/node devi anche aggiungere "types": ["node"]; altrimenti process e require restano sconosciuti (error TS2591: Cannot find name 'process'). Nella stessa lista vanno i test runner con funzioni globali, come il describe di Jest.

esModuleInterop fa funzionare gli import di default dei pacchetti CommonJS (import express from "express"). In TypeScript 7 è sempre attivo, e impostarlo a false è un errore.

skipLibCheck salta il controllo dei tipi dei file di dichiarazione. Velocizza le build ed evita errori dentro node_modules che non puoi correggere, al prezzo di non accorgerti dei conflitti tra i tipi di due librerie. La maggior parte dei progetti lo attiva.

Condividere le impostazioni con extends

extends carica un'altra configurazione e permette a questo file di sovrascriverne alcune parti:

{
    "extends": "./tsconfig.base.json",
    "compilerOptions": {
        "rootDir": "./src",
        "outDir": "./dist"
    },
    "include": ["src"]
}

Le compilerOptions vengono unite opzione per opzione, mentre include, exclude e files della base vengono sostituiti, non uniti, se questo file li imposta. I percorsi nel file base sono risolti rispetto al file base stesso. extends accetta anche un pacchetto: il progetto @tsconfig/bases ne pubblica uno per ogni ambiente, per esempio npm install --save-dev @tsconfig/node24 e poi "extends": "@tsconfig/node24/tsconfig.json".

Per vedere le impostazioni finali dopo aver applicato tutti gli extends e i valori predefiniti, esegui:

npx tsc --showConfig

Opzioni rimosse in TypeScript 7

TypeScript 6 ha deprecato queste impostazioni e TypeScript 7 le ha rimosse. Una configurazione che ne usa ancora una fallisce con error TS5108 o TS5102, per esempio Option 'baseUrl' has been removed. Please remove it from your configuration.

Impostazione rimossaUsa invece
"target": "es5"es2015 o successivo
"moduleResolution": "node" (node10) o "classic"nodenext o bundler
"module": "amd", "umd", "system", "none"nodenext, esnext o preserve, e un bundler per gli altri formati
baseUrlVoci di paths relative al file tsconfig
outFileUn bundler
downlevelIterationNiente: i target da es2015 in su supportano l'iterazione in modo nativo
"esModuleInterop": false, "allowSyntheticDefaultImports": false, "alwaysStrict": falseElimina la riga: sono sempre attive

La pagina su TypeScript 7 elenca gli altri cambiamenti di quella versione, compresi i nuovi valori predefiniti che questa tabella non copre.

Domande frequenti

Cos'è tsconfig.json?

È il file di configurazione di un progetto TypeScript. La sua presenza indica che la cartella è la radice del progetto, compilerOptions stabilisce come il compilatore controlla e genera il codice, e include, exclude o files dicono quali file fanno parte del progetto. Eseguire tsc senza argomenti lo legge.

Come creo un file tsconfig.json?

Esegui npx tsc --init nella cartella del progetto (con TypeScript installato). Scrive un tsconfig.json con le impostazioni consigliate e un commento su ogni opzione. Puoi anche scrivere il file a mano: {} è un tsconfig valido che usa tutti i valori predefiniti.

Che valore devo dare a target nel tsconfig?

La versione di JavaScript più vecchia su cui il tuo codice deve girare. Per le versioni attuali di Node.js, es2022 o successive vanno bene; il valore predefinito di TypeScript 7 è es2025. target decide quale sintassi più recente viene riscritta per i motori più vecchi e sceglie anche la lib predefinita, l'insieme di API integrate che il checker conosce.

Che differenza c'è tra module e moduleResolution?

module decide che tipo di codice di modulo scrive il compilatore (import/export ES o require CommonJS) e quali regole dei moduli si applicano. moduleResolution decide come un percorso di import come "./utils.js" o "lodash" viene trovato sul disco. Usa nodenext per il codice eseguito da Node.js e module: "preserve" (che implica la risoluzione bundler) per il codice elaborato da un bundler.

tsconfig.json può contenere commenti?

Sì. Il compilatore lo legge come JSON con commenti: sono ammessi i commenti // e /* */ e le virgole finali, ed è per questo che tsc --init scrive un file pieno di opzioni commentate. Altri strumenti che lo leggono come JSON rigoroso possono fallire su questi elementi.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA