Menu

TypeScript Strict Mode: was strict: true einschaltet

strict: true in tsconfig.json schaltet eine Familie von Typprüfungen ein: noImplicitAny, strictNullChecks, strictPropertyInitialization und fünf weitere. Was jede davon findet, wie du den Strict Mode in einem bestehenden Projekt aktivierst und welche nützlichen Flags strict nicht enthält.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

Der Strict Mode ist die Option "strict": true in tsconfig.json. Sie ist ein Schalter für acht Flags der Typprüfung, die implizites any, ungeprüftes null und undefined, unsichere Funktionszuweisungen und nicht initialisierte Klassenfelder finden. In TypeScript 7 ist strict standardmäßig aktiv. So sieht Code aus, der die Prüfung besteht:

Die Ausgabe ist no user, SyntaxError und 42. Entfernst du das : number, das ?. oder die Prüfung mit instanceof, kompiliert die Datei nicht mehr.

Einschalten

{
    "compilerOptions": {
        "strict": true
    }
}

Einzelne Flags haben Vorrang vor strict, in beide Richtungen. "strict": true, "strictNullChecks": false behält alles außer der Null-Prüfung; "strict": false, "noImplicitAny": true schaltet nur diese eine ein. Mit strict bekommst du außerdem Prüfungen, die in künftigen Versionen hinzukommen, da neue Flags der strict-Familie der Gruppe beitreten.

strict in TypeScript hat nichts mit der Direktive "use strict" von JavaScript zu tun, die ein Laufzeitmodus ist. TypeScript 7 erzeugt "use strict" immer dort, wo es nötig ist, und alwaysStrict: false zu setzen ist der Fehler TS5108 (die Option wurde entfernt).

Was jedes Flag findet

FlagWas es meldetFehler
noImplicitAnyeinen Parameter oder eine Variable, deren Typ stillschweigend any wäreTS7006 Parameter 'x' implicitly has an 'any' type.
strictNullChecksdie Verwendung eines Werts, der null oder undefined sein kannTS18048 'u' is possibly 'undefined'.
strictFunctionTypesdie Zuweisung einer Funktion, deren Parametertyp enger ist als verlangtTS2322
strictBindCallApplyfalsche Argumente an .call, .bind und .applyTS2345
strictPropertyInitializationein Klassenfeld, das nie zugewiesen wirdTS2564 Property 'name' has no initializer and is not definitely assigned in the constructor.
noImplicitThisthis mit implizitem Typ any, etwa in einer verschachtelten functionTS2683
useUnknownInCatchVariablesdie Verwendung einer catch-Variablen vor dem Einengen (sie ist unknown)TS18046 'err' is of type 'unknown'.
strictBuiltinIteratorReturnit.next().value eines eingebauten Iterators als immer definiert zu behandelnTS2322

Die beiden, die am meisten Code ändern, sind noImplicitAny und strictNullChecks. Dieser Block verletzt absichtlich beide:

Er gibt index.ts(2,17): error TS7006: Parameter 'x' implicitly has an 'any' type. und index.ts(11,13): error TS18048: 'user' is possibly 'undefined'. aus. Ohne strict kompiliert das und stürzt dann zur Laufzeit ab mit TypeError: Cannot read properties of undefined (reading 'name'). Mit strict wird der Absturz zu einem Compilerfehler. Die Lösungen stehen im ersten Block dieser Seite.

strictFunctionTypes: warum es das gibt

Eine Funktion, die nur Strings behandelt, darf nicht dort verwendet werden, wo Zahlen ankommen können. Die Prüfung unten ist mit @ts-expect-error stummgeschaltet, damit du sie ausführen und sehen kannst, was der Fehler verhindert:

Ohne den Kommentar ist die Zuweisung der Fehler TS2322, Type '(s: string) => void' is not assignable to type 'Handler'., gefolgt von Types of parameters 's' and 'value' are incompatible. Eine Ausnahme bleibt bewusst bestehen: Parameter von Methoden, die in Methodensyntax deklariert sind (handle(value: string | number): void in einem Interface), werden weiterhin lockerer geprüft, also ließe sich shout einer solchen Methode ohne Fehler zuweisen.

strictPropertyInitialization

Jedes Klassenfeld muss in seiner Deklaration oder im Konstruktor einen Wert bekommen. Drei Wege, das zu erfüllen:

Ausgabe:

Account {
  owner: 'Ada',
  balance: 0,
  history: [],
  lastLogin: undefined,
  sessionId: 's-1'
}

Die Eigenschaften lastLogin und sessionId existieren mit dem Wert undefined, weil Klassenfelder bei Target ES2022 echte JavaScript-Felder sind. Das ! entfernt die Prüfung, ohne zur Laufzeit etwas abzusichern, bevorzuge also die anderen Formen. Dieses Flag braucht strictNullChecks; schaltest du das ab, ist es ebenfalls aus.

Strict in einem bestehenden Projekt einschalten

Eine große Codebasis auf einen Schlag auf strict umzustellen kann Hunderte Fehler erzeugen. Weil strict in TypeScript 7 der Standard ist, schaltet das Upgrade eines Projekts, dessen tsconfig.json strict nie erwähnt hat, es von selbst ein; schreibe "strict": false, wenn du das alte Verhalten während der Migration brauchst. Ein Weg, bei dem der Build grün bleibt:

  1. Füge "strict": true hinzu und schalte die Flags mit den meisten Fehlern ab, meist "strictNullChecks": false und "noImplicitAny": false.
  2. Behebe die übrigen Fehler, schalte dann ein weiteres Flag ein und wiederhole.
  3. Bei noImplicitAny sind die meisten Lösungen Parameterannotationen. Bei strictNullChecks ergänzt du | undefined, wo Werte fehlen können, und behandelst das dann mit ?., ?? oder einer if-Prüfung.
  4. Wo eine Lösung warten muss, setze // @ts-expect-error mit einer Begründung auf die Zeile. Anders als @ts-ignore meldet es einen Fehler, sobald das Problem behoben ist, die Liste schrumpft also von selbst.

Greife nicht zu as any oder !, um Fehler in großer Zahl zum Schweigen zu bringen: Jedes davon verdeckt genau den Bug, für den das Flag eingeführt wurde.

Nützliche Flags, die strict nicht enthält

Diese sind separat, weil sie Code ablehnen, der oft korrekt ist. Viele Projekte schalten sie trotzdem ein.

FlagWas es tut
noUncheckedIndexedAccessarr[i] und record[key] enthalten undefined in ihrem Typ
exactOptionalPropertyTypesdebug?: boolean akzeptiert einen fehlenden Schlüssel, aber nicht debug: undefined
noImplicitReturnsjeder Codepfad einer Funktion mit Rückgabewert muss zurückgeben (TS7030)
noImplicitOverrideeine Methode, die eine Basismethode überschreibt, muss override angeben (TS4114)
noFallthroughCasesInSwitchein nicht leerer case muss mit break, return oder throw enden (TS7029)
noUnusedLocals, noUnusedParametersungenutzte Variablen und Parameter sind Fehler
noPropertyAccessFromIndexSignatureSchlüssel aus einer Index-Signatur müssen obj["key"] verwenden, nicht obj.key

noUncheckedIndexedAccess findet die meisten echten Bugs. Wenn es aktiv ist:

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);
}

tsc --init schaltet in TypeScript 7 in der erzeugten Konfiguration noUncheckedIndexedAccess und exactOptionalPropertyTypes ein, neben strict.

Häufig gestellte Fragen

Was macht der Strict Mode in TypeScript?

"strict": true aktiviert eine Gruppe strengerer Prüfungen: noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitThis, useUnknownInCatchVariables und strictBuiltinIteratorReturn. Zusammen verhindern sie, dass any unbemerkt auftaucht, und machen null und undefined zum Teil des Typsystems.

Ist der Strict Mode in TypeScript standardmäßig aktiv?

In TypeScript 7 ja: strict ist standardmäßig true, ein Projekt ohne Einstellung strict bekommt also jede strikte Prüfung. tsc --init schreibt "strict": true außerdem ausdrücklich hin. Um es abzuschalten, musst du "strict": false schreiben.

Kann ich eine strikte Prüfung abschalten und die übrigen behalten?

Ja. Einzelne Flags überschreiben strict: { "strict": true, "strictNullChecks": false } behält jede strikte Prüfung außer der Null-Prüfung. So migriert man üblicherweise eine große Codebasis Flag für Flag.

Ist der Strict Mode von TypeScript dasselbe wie "use strict" in JavaScript?

Nein. "use strict" ist ein Laufzeitmodus von JavaScript, der das Verhalten von Code ändert. strict in TypeScript ändert nur, was die Typprüfung meldet. TypeScript 7 erzeugt für Ausgaben, die keine Module sind, immer "use strict", und alwaysStrict: false ist inzwischen eine entfernte Option.

Enthält strict auch noUncheckedIndexedAccess?

Nein. noUncheckedIndexedAccess, exactOptionalPropertyTypes, noImplicitReturns, noImplicitOverride und noFallthroughCasesInSwitch sind eigene Flags, die du selbst einschaltest. tsc --init aktiviert die ersten beiden in der erzeugten Konfiguration.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S