--strict flag enthält die folgenden Flags:
--strictNullChecks--alwaysStrict--noImplicitAny--noImplicitThis--strictBindCallApply--strictFunctionTypes--strictPropertyInitializationHier sind einige Beispiele und versuchen Sie an einer Stelle zu verstehen, was dies alles bedeutet.// I. --strictNullChecks
Das berühmte Problem mit NPE (Nullzeiger-Ausnahme, Milliarden-Dollar-Fehler) im Zusammenhang mit TS.Standardmäßig sind in TS alle Typen Nullable und dies bedeutet, dass wir "undefined" | übergeben können "Null", wenn ein anderer Typ erwartet wird (sogar ein Grundelement):const bar1: { foo: number } = undefined;
const bar2: { foo: number } = null;
const bar3: number = null;
const bar4: string = null;
Interessantere Beispiele sind ein Methodenaufruf, der möglicherweise nicht vorhanden istdeclare var smth: { optionalMethod?(): string; };
smth.optionalMethod();
Es wird auch impliziert, dass wir "undefined" | nicht zurückgeben können "Null", wo dies eindeutig nicht erwartet wirdfunction getIt(): { data: number } {
return undefined;
}
getIt().data;
Wir müssen ausdrücklich angeben, dass "undefined" zurückkehren kann, und erst danach erhalten wir einen Fehlerfunction getIt(): { data: number } | undefined {
return undefined;
}
getIt().data;
Und als Bonus - sicherere Operationen, bei denen möglicherweise kein Ergebnis erzielt wird, tritt ein Fehler bei eingeschalteter Flagge auf, und Sie müssen explizit überprüfen, ob "find" etwas gefunden hat:
[{ name: 'John', age: 4 }]
.find(el => el.age === 42)
.name;
// II. - immer streng
Fügt jeder Datei die Anmerkung "use strict" hinzu , wodurch das JS-Verhalten expliziter wird// III. --noImplicitAny
Verbietet die implizite Verwendung von "any" in TS, d.h. Code ohne Typanmerkung
function id(arg) {
return arg;
}
Große Hilfe bei untypisierten Importen aus Bibliotheken von Drittanbietern, die die Installation von Typdefinitionen vorschlagen
import * as session from '3rd-party-lib';
// IV. --strictBindCallApply
Es enthält eine "strengere" Typprüfung für "Binden" / "Aufrufen" / "Anwenden" ohne Flag - dies ist alles ein gültiger TS. function getFullName(name: string, surname: string): string {
return name + surname;
}
getFullName.call(null, 'John', 42);
getFullName.apply(null, ['John', 42]);
getFullName.bind(null)('John');
getFullName.bind(null, 'John')();
getFullName.bind(null, 'John')(42);
// V. --strictPropertyInitialization + --strictNullChecks
Hilft zu verfolgen, dass alle Eigenschaften im Konstruktor initialisiert wurden. Sie müssen auch --strictNullChecks aktivieren, um Nullable-Typen zu deaktivieren. class User {
name: string;
}
Wenn sich die Zuweisung jedoch nicht im Konstruktor selbst befindet, überzeugen Sie TS davon, dass alles in Ordnung ist. class User2 {
name: string;
constructor(name: string) {
this.initializeName();
}
initializeName() {
this.name = 'John'
}
}
Wenn Sie TS nicht davon überzeugen konnten, dass die Eigenschaft genau initialisiert wird, können Sie sagen: "Ich schwöre bei Mama, ich werde definitiv initialisieren!" oder kurz "!"class User3 {
name!: string;
}
// VI. --strictFunctionTypes
Entfernt eine bivariante Prüfung auf Argumente.Kurz gesagt, Variante in der Programmierung - dies ist die Möglichkeit, Supertype / Subtype dort zu übergeben, wo Type erwartet wird. Zum Beispiel gibt es eine Hierarchie Form -> Kreis -> Rechteck. Ist es möglich, eine Form / ein Rechteck zu übertragen oder zurückzugeben, wenn Kreis erwartet wird ?Programmieroption habr , SOinterface Shape { name: string };
interface Circle extends Shape { width: number };
interface Rectangle extends Circle { height: number };
declare var logSC: (figure: Shape) => Circle;
declare var logRC: (figure: Rectangle) => Circle;
declare var logCC: (figure: Circle) => Circle;
declare var logCS: (figure: Circle) => Shape;
declare var logCR: (figure: Circle) => Rectangle;
declare var wlogBB: (fn: (figure: Circle) => Circle) => void;
wlogBB(logCC);
wlogBB(logSC);
wlogBB(logCR);
wlogBB(logCS);
wlogBB(logRC);
Es versteht sich, dass die Funktion das übergebene Argument (das als Typproduzent fungiert) nicht mutieren sollte, es gibt tatsächlich keine Fehler in TS - es gibtconst squares: Square[] = [{ name: 'Square', width: 5 }];
function addSmth(arg: Shape[]) {
arg.push({ name: 'Square' });
}
addSmth(squares);
// VII. --noImplicitThis
Wenn die Funktion außerhalb des Objekts / der Klasse definiert ist, werden Sie von TS aufgefordert, explizit anzugeben, worauf sich "dies" bezieht, indem Sie das erste Pseudoargument mit dem Namen "dies" verwenden.
function getName(this: { name: string }, surname: string): string {
return this.name;
}
getName.call({}, 'Smith');
getName.apply({}, ['Smith']);
getName.bind({})('Smith');
Anrufe sind gültigconst somePerson = { name: 'John', getName };
const fullName: string = somePerson.getName('Smith')
getName.call({name: 'John'}, 'Smith');
getName.apply({name: 'John'}, ['Smith']);
getName.bind({name: 'John'})('Smith');
Konstruktorfunktionen können Probleme verursachenfunction Person(this: { name: string }, name: string) {
this.name = name;
}
const person = new Person('John');
Ein interessanter Bonus ist das Hinzufügen eines Vergleichs der Kontextbindungsmethoden für Klassen.class A {
x = 42;
constructor() {
this.getBound = this.getBound.bind(this);
}
getSimple(): number {
return this.x;
}
getSimpleAnnotated(this: A): number {
return this.x;
}
getArrow = (): number => this.x;
getBound(this: A): number {
return this.x;
}
}
const a = new A();
const getSimple = a.getSimple;
getSimple();
const getSimpleAnnotated = a.getSimpleAnnotated;
getSimpleAnnotated();
const getArrow = a.getArrow;
getArrow();
const getBound = a.getBound;
getBound();