Lo strict mode è l'opzione "strict": true di tsconfig.json. È un unico interruttore per otto opzioni di controllo dei tipi che intercettano any impliciti, null e undefined non controllati, assegnazioni di funzioni non sicure e campi di classe non inizializzati. In TypeScript 7, strict è attivo di default. Ecco come appare del codice che lo supera:
L'output è no user, SyntaxError e 42. Togli il : number, il ?. o il controllo instanceof e il file non compila più.
Come attivarlo
{
"compilerOptions": {
"strict": true
}
}
Le singole opzioni prevalgono su strict, in entrambe le direzioni. "strict": true, "strictNullChecks": false mantiene tutto tranne il controllo su null; "strict": false, "noImplicitAny": true attiva solo quella. strict ti iscrive anche ai controlli aggiunti nelle versioni future, perché le nuove opzioni della famiglia strict entrano nel gruppo.
Lo strict di TypeScript non ha niente a che vedere con la direttiva "use strict" di JavaScript, che è una modalità di esecuzione. TypeScript 7 emette sempre "use strict" dove serve, e impostare alwaysStrict: false è l'errore TS5108 (l'opzione è stata rimossa).
Cosa intercetta ogni opzione
| Opzione | Cosa segnala | Errore |
|---|---|---|
noImplicitAny | un parametro o una variabile il cui tipo sarebbe silenziosamente any | TS7006 Parameter 'x' implicitly has an 'any' type. |
strictNullChecks | l'uso di un valore che può essere null o undefined | TS18048 'u' is possibly 'undefined'. |
strictFunctionTypes | l'assegnazione di una funzione con un tipo di parametro più ristretto del richiesto | TS2322 |
strictBindCallApply | argomenti sbagliati a .call, .bind e .apply | TS2345 |
strictPropertyInitialization | un campo di classe che non viene mai assegnato | TS2564 Property 'name' has no initializer and is not definitely assigned in the constructor. |
noImplicitThis | this con un tipo any implicito, come in una function annidata | TS2683 |
useUnknownInCatchVariables | l'uso di una variabile di catch prima di restringerla (è unknown) | TS18046 'err' is of type 'unknown'. |
strictBuiltinIteratorReturn | trattare it.next().value di un iteratore built-in come sempre definito | TS2322 |
Le due che cambiano più codice sono noImplicitAny e strictNullChecks. Questo blocco le viola entrambe di proposito:
Stampa index.ts(2,17): error TS7006: Parameter 'x' implicitly has an 'any' type. e index.ts(11,13): error TS18048: 'user' is possibly 'undefined'. Senza strict, compila e poi va in crash in esecuzione con TypeError: Cannot read properties of undefined (reading 'name'). Con strict, il crash diventa un errore di compilazione. Le correzioni sono nel primo blocco di questa pagina.
strictFunctionTypes: perché esiste
Una funzione che gestisce solo stringhe non deve essere usata dove possono arrivare numeri. Il controllo qui sotto è zittito con @ts-expect-error, così puoi eseguirlo e vedere cosa previene l'errore:
Senza il commento, l'assegnazione è l'errore TS2322, Type '(s: string) => void' is not assignable to type 'Handler'., seguito da Types of parameters 's' and 'value' are incompatible. Resta un'eccezione voluta: i parametri dei metodi dichiarati con la sintassi dei metodi (handle(value: string | number): void dentro un'interfaccia) vengono ancora controllati in modo più permissivo, quindi shout si potrebbe assegnare a un metodo del genere senza errori.
strictPropertyInitialization
Ogni campo di classe deve ricevere un valore nella dichiarazione o nel costruttore. Tre modi per soddisfare il controllo:
Output:
Account {
owner: 'Ada',
balance: 0,
history: [],
lastLogin: undefined,
sessionId: 's-1'
}
Le proprietà lastLogin e sessionId esistono con il valore undefined perché con target ES2022 i campi di classe sono veri campi JavaScript. Il ! elimina il controllo senza aggiungere alcuna protezione in esecuzione, quindi preferisci le altre forme. Questa opzione richiede strictNullChecks: se disattivi quella, si disattiva anche questa.
Attivare strict in un progetto esistente
Passare una codebase grande a strict tutto in una volta può produrre centinaia di errori. Dato che strict è il default di TypeScript 7, aggiornare un progetto il cui tsconfig.json non ha mai menzionato strict lo attiva da solo; scrivi "strict": false se ti serve il vecchio comportamento durante la migrazione. Un percorso che mantiene la build verde:
- Aggiungi
"strict": truee disattiva le opzioni con più errori, di solito"strictNullChecks": falsee"noImplicitAny": false. - Correggi gli errori rimasti, poi attiva un'altra opzione e ripeti.
- Per
noImplicitAny, la maggior parte delle correzioni sono annotazioni sui parametri. PerstrictNullChecks, aggiungi| undefineddove i valori possono mancare, poi gestiscilo con?.,??o un controlloif. - Dove una correzione deve aspettare, metti sulla riga
// @ts-expect-errorcon un motivo. A differenza di@ts-ignore, segnala un errore quando il problema sparisce, così la lista si accorcia da sola.
Non usare as any o ! per zittire gli errori in blocco: ognuno nasconde proprio il bug che l'opzione doveva trovare.
Opzioni utili che strict non include
Sono separate perché rifiutano codice che spesso è corretto. Molti progetti le attivano comunque.
| Opzione | Cosa fa |
|---|---|
noUncheckedIndexedAccess | arr[i] e record[key] includono undefined nel loro tipo |
exactOptionalPropertyTypes | debug?: boolean accetta una chiave mancante ma non debug: undefined |
noImplicitReturns | ogni percorso di una funzione che restituisce un valore deve fare return (TS7030) |
noImplicitOverride | un metodo che sovrascrive un metodo della classe base deve dire override (TS4114) |
noFallthroughCasesInSwitch | un case non vuoto deve terminare con break, return o throw (TS7029) |
noUnusedLocals, noUnusedParameters | variabili e parametri inutilizzati sono errori |
noPropertyAccessFromIndexSignature | le chiavi di una index signature devono usare obj["key"], non obj.key |
noUncheckedIndexedAccess è quella che intercetta più bug reali. Con l'opzione attiva:
const scores = [90, 85];
const d: Record<string, number> = {};
const third: number = scores[2]; // error TS2322: Type 'number | undefined' is not assignable to type 'number'.
const c: number = d["x"]; // same error
const safe = scores[2] ?? 0; // number
for (const s of scores) { // for...of is not affected: s is number
console.log(s);
}
In TypeScript 7, tsc --init attiva noUncheckedIndexedAccess e exactOptionalPropertyTypes nella configurazione che genera, accanto a strict.
Domande frequenti
Cosa fa lo strict mode in TypeScript?
"strict": true attiva un gruppo di controlli più severi: noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitThis, useUnknownInCatchVariables e strictBuiltinIteratorReturn. Insieme impediscono che any compaia in silenzio e fanno entrare null e undefined nel sistema dei tipi.
Lo strict mode è attivo di default in TypeScript?
In TypeScript 7 sì: strict vale true di default, quindi un progetto senza alcuna impostazione strict riceve tutti i controlli strict. Anche tsc --init scrive "strict": true in modo esplicito. Per disattivarlo devi scrivere "strict": false.
Posso disattivare un solo controllo strict e tenere gli altri?
Sì. Le singole opzioni hanno la precedenza su strict: { "strict": true, "strictNullChecks": false } mantiene tutti i controlli strict tranne quello su null. È il modo abituale per migrare una codebase grande un'opzione alla volta.
Lo strict mode di TypeScript è lo stesso di "use strict" in JavaScript?
No. "use strict" è una modalità di esecuzione di JavaScript che cambia il comportamento del codice. Lo strict di TypeScript cambia solo ciò che segnala il type checker. TypeScript 7 emette sempre "use strict" nell'output non modulare, e alwaysStrict: false è ora un'opzione rimossa.
strict include noUncheckedIndexedAccess?
No. noUncheckedIndexedAccess, exactOptionalPropertyTypes, noImplicitReturns, noImplicitOverride e noFallthroughCasesInSwitch sono opzioni separate che attivi tu. tsc --init attiva le prime due nella configurazione che genera.