Im vorherigen Teil dieser Beitragsreihe haben wir über die sichere Nullbarkeit gesprochen.
Jetzt erklären und lösen wir das dritte und letzte Problem des TypeScript-Standardverhaltens: Überbleibsel der dynamischen Typisierung.
Wir werden Folgendes abdecken:
TypeScript soll ein „statischer Typprüfer“ sein, im Gegensatz zu JavaScript, bei dem die Eingabe sehr dynamisch ist.
Aber in einem früheren Teil dieser Beitragsreihe haben wir auch erklärt, dass TypeScript als Obermenge von JavaScript aufgebaut ist.
Das Problem ist also: Einige Teile des dynamischen JavaScript-Typisierungssystems verbleiben in TypeScript. Wir werden daher erklären, wie man diese verbleibenden Verhaltensweisen unterdrückt, um eine vollständige statische Typisierung zu erreichen.
Das beste Beispiel für das Problem sind Gleichheitsprüfungen. In JavaScript ist == nicht gerade eine Gleichheitsprüfung, sondern eine Äquivalenzprüfung:
1 == "1"; // true
Obwohl die Typen unterschiedlich sind, kommen einige Konvertierungsregeln zum Tragen, damit JavaScript die Werte vergleichen kann. Dies kann zu vielen Fehlern führen, da die Regeldetails schwer zu merken sind, manchmal ziemlich seltsam sind und nicht in allen dynamischen Sprachen (wie z. B. PHP) genau gleich sind.
Diese Äquivalenzprüfungen sind nur in einer dynamisch typisierten Sprache wie JavaScript sinnvoll. Von dem Moment an, in dem wir uns entscheiden, in TypeScript zu arbeiten, sollten nur noch tatsächliche Gleichheitsprüfungen (Typ und Wert) verwendet werden.
1 === "1"; // false
Die eqeqeq-Lint-Regel erzwingt dies.
Benutzer von Sprachen wie Java, C# oder Rust sollten mit diesem Problem besonders vorsichtig sein, da == in JavaScript oder TypeScript nicht dasselbe bedeutet wie in diesen Sprachen. In JavaScript und TypeScript ist ein drittes = erforderlich, um dasselbe Verhalten zu erreichen.
Denken Sie, dass die Bedingungen jetzt sicher sind? Leider nicht, da Konvertierungen implizit sein können:
let tax: number | undefined = 0; if (tax) { console.log("Process payment"); } if (!tax) { throw new Error(); }
Das obige Beispiel entspricht:
let tax: number | undefined = 0; if (tax == true) { console.log("Process payment"); } if (tax == false) { throw new Error(); }
Wie Sie sehen können, gab es implizite ==, daher finden immer noch Konvertierungen statt: 0 ist nicht gleichbedeutend mit wahr, sondern gleichbedeutend mit falsch. Es kommt also zu einem Fehler, obwohl die Steuer ein gültiger Wert ist.
Die Lint-Regel strict-boolean-expressions verbietet solche impliziten Bedingungen und erzwingt tatsächliche Prüfungen:
let tax: number | undefined = 0; if (tax !== undefined) { console.log("Process payment"); } if (tax === undefined) { throw new Error(); }
Für Leute, die an schnelle Bedingungen in JavaScript gewöhnt sind, mag dies eine der mühsamsten Regeln sein, aber um es ins rechte Licht zu rücken: Es ist einfach die normale Art, Dinge in anderen Sprachen wie Java, C# oder Rust zu erledigen.
Wie im Konfigurationsteil gezeigt, ist das Deaktivieren der Unteroptionen „allowNumber“ und „allowString“ wichtig, um alle Fehler zu vermeiden.
Die einzige zulässige Ausnahme gilt für Objekte und Arrays: Diese Fälle sind sicher, da sie im Gegensatz zu Zeichenfolgen und Zahlen keine falschen Werte haben. Folgendes ist also noch in Ordnung:
let movie: Movie | undefined; if (movie) {} if (!movie) {}
Hinweis: Switch-Anweisungen sind bereits sicher, da sie intern === verwenden.
Die Lint-Regel strict-boolean-expressions sorgt dafür, dass Bedingungsprüfungen typsicher sind, es gibt jedoch andere Bedingungssyntaxen als if:
const movieRating = userRating || 5; // Which is a shorter version of: const movieRating = userRating == true ? userRating : 5;
Wenn der Benutzer 0 bewertet hat, entspricht 0 „falsch“, sodass die Bewertung 5 statt 0 beträgt.
Es kann mit modernem JavaScript vermieden werden:
const movieRating = userRating ?? 5; // Which is a shorter version of: const movieRating = userRating !== undefined && userRating !== null ? userRating : 5;
Dies kann durch die Prefer-Nullish-Coalescing-Lint-Regel erzwungen werden.
Beachten Sie, dass ?? sollte nicht überall verwendet werden: || ist immer noch relevant, wenn mit Booleschen Werten gearbeitet wird.
In JavaScript kann der Operator sowohl für die mathematische Addition von Zahlen als auch für die Verkettung von Zeichenfolgen verwendet werden. Es führt zu einem Fehler.
"There is " 3 1 "Matrix movies"; // 31 "There is " (3 1) "Matrix movies"; // 4
Der Operator sollte für die mathematische Addition reserviert sein. Zumindest sollte es nur mit Daten desselben Typs verwendet werden, was durch die Lint-Regel „Restrict-Plus-Operands“ erzwungen wird.
Vorlagenzeichenfolgen aus modernem JavaScript sollten für die Zeichenfolgenverkettung verwendet werden, was durch die Prefer-Template-Lint-Regel erzwungen wird:
const movie = `Everything everywhere all at once`; `${movie} is the best movie!`;
Umgekehrt sollten in Vorlagenzeichenfolgen nur Zeichenfolgen verwendet werden, was durch die Lint-Regel „restrict-template-expressions“ erzwungen wird.
Wenn das Mischen von Typen tatsächlich gewünscht ist, sollten Konvertierungen explizit erfolgen:
const total = 3; `There is ${total.toFixed()} Matrix movies`;
Beachten Sie, dass Vorlagenzeichenfolgen verschachtelt werden können:
const total = 3; `There is ${total.toFixed()} Matrix movie${total > 1 ? "s" : ""}`;
Dies ist das Ende dieser Beitragsreihe. Sie können meinem Konto folgen (Schaltfläche oben rechts auf dieser Seite), um zu erfahren, wann andere Beiträge zu TypeScript oder anderen Themen wie Angular veröffentlicht werden.
Sie möchten mit mir Kontakt aufnehmen? Anweisungen finden Sie in der Zusammenfassung.
Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.
Copyright© 2022 湘ICP备2022001581号-3