Menu

Mode strict TypeScript : ce qu'active strict: true

strict: true dans tsconfig.json active une famille de vérifications de types : noImplicitAny, strictNullChecks, strictPropertyInitialization et cinq autres. Voyez ce que chacune détecte, comment activer le mode strict dans un projet existant, et les options utiles que strict n'inclut pas.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

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

OptionCe qu'elle signaleErreur
noImplicitAnyun paramètre ou une variable dont le type serait any en silenceTS7006 Parameter 'x' implicitly has an 'any' type.
strictNullChecksl'utilisation d'une valeur qui peut être null ou undefinedTS18048 'u' is possibly 'undefined'.
strictFunctionTypesl'affectation d'une fonction dont le type de paramètre est plus étroit que requisTS2322
strictBindCallApplyde mauvais arguments passés à .call, .bind et .applyTS2345
strictPropertyInitializationun champ de classe jamais affectéTS2564 Property 'name' has no initializer and is not definitely assigned in the constructor.
noImplicitThisthis avec un type any implicite, comme dans une function imbriquéeTS2683
useUnknownInCatchVariablesl'utilisation d'une variable de catch avant d'avoir restreint son type (elle est unknown)TS18046 'err' is of type 'unknown'.
strictBuiltinIteratorReturnconsidérer que le it.next().value d'un itérateur intégré est toujours définiTS2322

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 :

  1. Ajoutez "strict": true et désactivez les options qui produisent le plus d'erreurs, généralement "strictNullChecks": false et "noImplicitAny": false.
  2. Corrigez les erreurs restantes, puis activez une option de plus et recommencez.
  3. Pour noImplicitAny, la plupart des corrections sont des annotations de paramètres. Pour strictNullChecks, ajoutez | undefined là où des valeurs peuvent manquer, puis gérez ce cas avec ?., ?? ou un test if.
  4. Quand une correction doit attendre, placez // @ts-expect-error avec 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.

OptionCe qu'elle fait
noUncheckedIndexedAccessarr[i] et record[key] incluent undefined dans leur type
exactOptionalPropertyTypesdebug?: boolean accepte une clé absente mais pas debug: undefined
noImplicitReturnschaque chemin d'une fonction qui renvoie une valeur doit renvoyer (TS7030)
noImplicitOverrideune méthode qui redéfinit une méthode de base doit indiquer override (TS4114)
noFallthroughCasesInSwitchun case non vide doit se terminer par break, return ou throw (TS7029)
noUnusedLocals, noUnusedParametersles variables et paramètres inutilisés sont des erreurs
noPropertyAccessFromIndexSignatureles 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.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER