Le mode strict, c'est l'option "strict": true du tsconfig.json. Un seul interrupteur pour huit options de vérification des types, qui détectent les any implicites, les null et undefined non vérifiés, les affectations de fonctions dangereuses et les champs de classe non initialisés. Dans TypeScript 7, strict est activé par défaut. Voici à quoi ressemble du code qui le passe :
La sortie est no user, SyntaxError et 42. Retirez le : number, le ?. ou le test instanceof et le fichier ne compile plus.
L'activer
{
"compilerOptions": {
"strict": true
}
}
Les options individuelles l'emportent sur strict, dans les deux sens. "strict": true, "strictNullChecks": false garde tout sauf la vérification des null ; "strict": false, "noImplicitAny": true n'active que cette option. strict vous inscrit aussi aux vérifications ajoutées dans les versions futures, puisque les nouvelles options de la famille strict rejoignent le groupe.
Le strict de TypeScript n'a rien à voir avec la directive "use strict" de JavaScript, qui est un mode d'exécution. TypeScript 7 émet toujours "use strict" là où il le faut, et régler alwaysStrict: false provoque l'erreur TS5108 (l'option a été supprimée).
Ce que détecte chaque option
| Option | Ce qu'elle signale | Erreur |
|---|---|---|
noImplicitAny | un paramètre ou une variable dont le type serait any en silence | TS7006 Parameter 'x' implicitly has an 'any' type. |
strictNullChecks | l'utilisation d'une valeur qui peut être null ou undefined | TS18048 'u' is possibly 'undefined'. |
strictFunctionTypes | l'affectation d'une fonction dont le type de paramètre est plus étroit que requis | TS2322 |
strictBindCallApply | de mauvais arguments passés à .call, .bind et .apply | TS2345 |
strictPropertyInitialization | un champ de classe jamais affecté | TS2564 Property 'name' has no initializer and is not definitely assigned in the constructor. |
noImplicitThis | this avec un type any implicite, comme dans une function imbriquée | TS2683 |
useUnknownInCatchVariables | l'utilisation d'une variable de catch avant d'avoir restreint son type (elle est unknown) | TS18046 'err' is of type 'unknown'. |
strictBuiltinIteratorReturn | considérer que le it.next().value d'un itérateur intégré est toujours défini | TS2322 |
Les deux qui changent le plus de code sont noImplicitAny et strictNullChecks. Ce bloc les enfreint toutes les deux exprès :
Il affiche index.ts(2,17): error TS7006: Parameter 'x' implicitly has an 'any' type. et index.ts(11,13): error TS18048: 'user' is possibly 'undefined'. Sans strict, ce code compile puis plante à l'exécution avec TypeError: Cannot read properties of undefined (reading 'name'). Avec strict, le plantage devient une erreur de compilation. Les corrections sont dans le premier bloc de cette page.
strictFunctionTypes : pourquoi elle existe
Une fonction qui ne gère que des chaînes ne doit pas être utilisée là où des nombres peuvent arriver. La vérification ci-dessous est réduite au silence avec @ts-expect-error pour que vous puissiez l'exécuter et voir ce que l'erreur évite :
Sans le commentaire, l'affectation provoque l'erreur TS2322, Type '(s: string) => void' is not assignable to type 'Handler'., suivie de Types of parameters 's' and 'value' are incompatible. Une exception subsiste volontairement : les paramètres des méthodes déclarées avec la syntaxe de méthode (handle(value: string | number): void dans une interface) sont toujours vérifiés de la façon plus souple, donc shout pourrait être affectée à une telle méthode sans erreur.
strictPropertyInitialization
Chaque champ de classe doit recevoir une valeur dans sa déclaration ou dans le constructeur. Trois façons de satisfaire cette règle :
Sortie :
Account {
owner: 'Ada',
balance: 0,
history: [],
lastLogin: undefined,
sessionId: 's-1'
}
Les propriétés lastLogin et sessionId existent avec la valeur undefined parce que les champs de classe sont de vrais champs JavaScript avec la cible ES2022. Le ! supprime la vérification sans ajouter aucune protection à l'exécution : préférez donc les autres formes. Cette option a besoin de strictNullChecks ; désactiver celle-ci la désactive aussi.
Activer strict dans un projet existant
Passer une grosse base de code en strict d'un coup peut produire des centaines d'erreurs. Comme strict est la valeur par défaut de TypeScript 7, mettre à jour un projet dont le tsconfig.json ne mentionnait jamais strict l'active tout seul ; écrivez "strict": false si vous avez besoin de l'ancien comportement pendant la migration. Une démarche qui garde le build au vert :
- Ajoutez
"strict": trueet désactivez les options qui produisent le plus d'erreurs, généralement"strictNullChecks": falseet"noImplicitAny": false. - Corrigez les erreurs restantes, puis activez une option de plus et recommencez.
- Pour
noImplicitAny, la plupart des corrections sont des annotations de paramètres. PourstrictNullChecks, ajoutez| undefinedlà où des valeurs peuvent manquer, puis gérez ce cas avec?.,??ou un testif. - Quand une correction doit attendre, placez
// @ts-expect-erroravec une raison sur la ligne. Contrairement à@ts-ignore, il signale une erreur dès que le problème a disparu, donc la liste diminue d'elle-même.
N'utilisez pas as any ni ! pour faire taire les erreurs en masse : chacun cache exactement le bug que l'option devait trouver.
Options utiles que strict n'inclut pas
Elles sont séparées parce qu'elles refusent du code souvent correct. Beaucoup de projets les activent quand même.
| Option | Ce qu'elle fait |
|---|---|
noUncheckedIndexedAccess | arr[i] et record[key] incluent undefined dans leur type |
exactOptionalPropertyTypes | debug?: boolean accepte une clé absente mais pas debug: undefined |
noImplicitReturns | chaque chemin d'une fonction qui renvoie une valeur doit renvoyer (TS7030) |
noImplicitOverride | une méthode qui redéfinit une méthode de base doit indiquer override (TS4114) |
noFallthroughCasesInSwitch | un case non vide doit se terminer par break, return ou throw (TS7029) |
noUnusedLocals, noUnusedParameters | les variables et paramètres inutilisés sont des erreurs |
noPropertyAccessFromIndexSignature | les clés d'une index signature doivent utiliser obj["key"], pas obj.key |
noUncheckedIndexedAccess est celle qui attrape le plus de vrais bugs. Quand elle est activée :
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);
}
Dans TypeScript 7, tsc --init active noUncheckedIndexedAccess et exactOptionalPropertyTypes dans la configuration qu'il génère, à côté de strict.
Questions fréquentes
Que fait le mode strict en TypeScript ?
"strict": true active un groupe de vérifications plus strictes : noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitThis, useUnknownInCatchVariables et strictBuiltinIteratorReturn. Ensemble, elles empêchent any d'apparaître en silence et font de null et undefined une partie du système de types.
Le mode strict est-il activé par défaut en TypeScript ?
Dans TypeScript 7, oui : strict vaut true par défaut, donc un projet sans réglage strict obtient toutes les vérifications strictes. tsc --init écrit aussi "strict": true explicitement. Pour s'en passer, il faut écrire "strict": false.
Peut-on désactiver une seule vérification stricte et garder les autres ?
Oui. Les options individuelles l'emportent sur strict : { "strict": true, "strictNullChecks": false } garde toutes les vérifications strictes sauf celle des null. C'est la façon habituelle de migrer une grosse base de code option par option.
Le mode strict de TypeScript est-il le même que le "use strict" de JavaScript ?
Non. "use strict" est un mode d'exécution de JavaScript qui change le comportement du code. Le strict de TypeScript ne change que ce que signale le vérificateur de types. TypeScript 7 émet toujours "use strict" pour une sortie qui n'est pas un module, et alwaysStrict: false est désormais une option supprimée.
strict inclut-il noUncheckedIndexedAccess ?
Non. noUncheckedIndexedAccess, exactOptionalPropertyTypes, noImplicitReturns, noImplicitOverride et noFallthroughCasesInSwitch sont des options séparées que vous activez vous-même. tsc --init active les deux premières dans la configuration qu'il génère.