Il file tsconfig.json, come abbiamo visto nella lezione sulla configurazione dei progetti TypeScript, permette di configurare il comportamento del compilatore TypeScript. In questa lezione analizziamo alcune delle opzioni più importanti per controllare la qualità del codice, la compilazione e la struttura dei file generati.
Il file tsconfig.json si trova sempre nella cartella principale del progetto TypeScript.
TypeScript può effettuare controlli più o meno rigorosi sul codice.
Un progetto può essere configurato con diversi livelli di controllo attraverso alcune opzioni specifiche.
L'opzione strict: true abilita un insieme di controlli di tipo più rigorosi. Si può impostare in questo modo:
{
"compilerOptions": {
"strict": true
}
}È generalmente consigliabile utilizzare strict: true nei nuovi progetti, perché permette di individuare più errori durante la compilazione invece di lasciarli emergere successivamente durante l'esecuzione.
strict comprende diverse impostazioni di controllo, tra cui quelle relative a any impliciti (ovvero tipi sconosciuti) e null o undefined.
TypeScript può talvolta trovarsi davanti a un valore il cui tipo non è stato specificato e non può essere determinato automaticamente.
Ad esempio:
function stampa(valore) {
console.log(valore);
}Se il compilatore non riesce a determinare il tipo del parametro, potrebbe considerarlo implicitamente any.
Impostiamo noImplicitAny: true in questo modo:
{
"compilerOptions": {
"noImplicitAny": true
}
}Con questa impostazione, TypeScript segnala un errore quando un valore assume implicitamente il tipo any in situazioni in cui il tipo dovrebbe essere esplicitato.
Possiamo risolvere il problema specificando il tipo:
function stampa(valore: string) {
console.log(valore);
}Questa impostazione aiuta quindi a evitare che any venga introdotto accidentalmente nel codice.
L'opzione strictNullChecks controlla il modo in cui TypeScript tratta null e undefined, che abbiamo visto tra i tipi primitivi.
{
"compilerOptions": {
"strictNullChecks": true
}
}Con questa impostazione in tsconfig.json, null e undefined vengono trattati come valori distinti dagli altri tipi.
Ad esempio:
let nome: string = "Andrea";Nell'esempio, non sarebbe permesso assegnare nome = null; perché null non è una string.
Se invece vogliamo consentire esplicitamente anche null, dobbiamo utilizzare un'unione di tipi:
let nome: string | null = null;Questo comportamento permette di individuare più facilmente situazioni in cui un valore potrebbe essere assente.
L'opzione noImplicitReturns: true controlla le funzioni che prevedono un valore di ritorno e segnala situazioni in cui non tutti i percorsi della funzione restituiscono un valore.
{
"compilerOptions": {
"noImplicitReturns": true
}
}Ora proviamo a guardare questa funzione:
function verificaNumero(numero: number): string {
if (numero > 0) {
return "Positivo";
}
}La funzione dichiara di restituire una string, ma quando numero è minore o uguale a zero non viene eseguito alcun return.
Possiamo correggerla gestendo tutti i casi:
function verificaNumero(numero: number): string {
if (numero > 0) {
return "Positivo";
}
return "Non positivo";
}Oltre ai controlli sul codice, tsconfig.json permette di stabilire come deve essere compilato il codice TypeScript.
L'opzione target stabilisce quale versione di JavaScript deve essere generata dal compilatore.
Ad esempio:
{
"compilerOptions": {
"target": "ES2022"
}
}TypeScript può quindi trasformare il codice in JavaScript compatibile con quella versione.
Un target più moderno permette di mantenere nel codice generato funzionalità JavaScript moderne. Un target più vecchio, invece, può richiedere a TypeScript di trasformare alcune funzionalità in codice compatibile con ambienti meno recenti.
L'opzione module stabilisce quale sistema di moduli deve essere utilizzato dal codice JavaScript generato. Ad esempio:
{
"compilerOptions": {
"module": "ESNext"
}
}L'opzione nell'esempio può essere utilizzata in progetti basati sui moduli JavaScript moderni.
In un progetto Node.js, invece, la configurazione può dipendere dal sistema di moduli utilizzato dal progetto, ad esempio CommonJS oppure le modalità moderne di Node.js.
Il valore di module deve quindi essere scelto in base all'ambiente di esecuzione e alla struttura del progetto.
L'opzione moduleResolution stabilisce come TypeScript deve trovare i moduli importati dal codice (puoi approfondire meglio nella lezione sui moduli e librerie esterne in TypeScript che abbiamo già visto).
Ad esempio:
import { somma } from "./matematica";TypeScript deve determinare quale file corrisponde al modulo ./matematica. L'opzione moduleResolution controlla proprio queste regole di ricerca.
Nei progetti moderni è comune utilizzare modalità come:
{
"compilerOptions": {
"moduleResolution": "NodeNext"
}
}L'opzione rootDir indica la cartella principale che contiene i file sorgente del progetto TypeScript.
Ad esempio, se i file principali del progetto si trovano in /src:
{
"compilerOptions": {
"rootDir": "./src"
}
}L'opzione outDir stabilisce dove devono essere inseriti i file JavaScript generati dalla compilazione dei file TypeScript.
Ad esempio, se i file JavaScript devono essere inseriti in /dist:
{
"compilerOptions": {
"outDir": "./dist"
}
}L'opzione include permette di specificare quali file devono essere inclusi nella compilazione.
Ad esempio, per includere i file TypeScript presenti nella cartella src e nelle relative sottocartelle, possiamo scrivere:
{
"include": [
"src/**/*.ts"
]
}Possiamo specificare anche una singola cartella:
{
"include": ["src"]
}Oppure possiamo indicare più percorsi:
{
"include": [
"src",
"tests"
]
}L'opzione exclude permette invece di indicare file o cartelle che non devono essere inclusi nella compilazione.
Un esempio comune è:
{
"exclude": [
"node_modules"
]
}