Programmiersprache TypeScript 4.9 verbietet GleichheitsprĂĽfung mit Not a Number
Neben dem strikteren Umgang mit NaN bringt das Release den neuen Operator satisfies und verbessert den Umgang mit dem in-Operator.
(Bild: , gemeinfrei)
Sieben Wochen nach der ersten Beta hat Microsoft das stabile Release von TypeScript 4.9 veröffentlicht. Das JavaScript-Superset führt den neuen Operator satisfies ein und verbietet Gleichheitsprüfungen mit NaN. Außerdem bietet der in-Operator deutlichere Typzuweisungen für den Schlüssel und das Objekt.
Videos by heise
Keine Zahl kennt keine Gleichheit
TypeScript 4.9 schafft mehr Klarheit im Umgang mit dem Spezialwert NaN, der für Not a Number, also keine Zahl steht. Für TypeScript, JavaScript und alle anderen Sprachen, die Gleitkommazahlen nach IEEE 754 implementieren legt die Spezifikation fest, dass Gleichheitschecks zu NaN grundsätzlich false ergeben.
Ein immer wieder auftauchender Fehler ist, mit != zu prĂĽfen, ob ein Wert nicht NaN ist. Da jedoch auch NaN per Definition ebenso wie alle anderen Werte ungleich NaN ist, ist das Ergebnis immer true und der Vergleich sinnlos:
console.log(NaN == NaN) // false
console.log(NaN != NaN) // true
Daher verbietet TypeScript ab sofort Gleichheits- und Ungleichheitsprüfungen auf Not a Number und schlägt stattdessen den Einsatz der Methode Number.isNaN() vor:
function validate(someValue: number) {
return someValue !== NaN;
// ~~~~~~~~~~~~~~~~~
// error: This condition will always return 'true'.
// Did you mean '!Number.isNaN(someValue)'?
}
Voraussetzung erfĂĽllt, Typ erhalten
Der neue Operator satisfies prüft, ob ein Ausdruck einem bestimmten Typ entspricht, ohne den Typ des Ausdrucks zu ändern beziehungsweise über Typannotationen zuzuweisen. Folgendes zusammengefasste Beispiel aus dem TypeScript-Blog zeigt den Unterschied.
type Colors = "red" | "green" | "blue";
type RGB = [red: number, green: number, blue: number];
const palette1: Record<Colors, string | RGB> = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0, 255]
};
const palette2 = {
red: [255, 0, 0],
green: "#00ff00",
blue: [0, 0, 255]
} satisfies Record<Colors, string | RGB>;
// Fehler: (string | RGB)
const green1Normalized = palette1.green.toUpperCase();
// Korrekte Typinferrenz (string)
const green2Normalized = palette2.green.toUpperCase();
palette1 verwendet Typannotation, womit aber der Zugriff auf die Funktion toUpperCase nicht erlaubt ist. palette2 prĂĽft dagegen nur die korrekten Typen, ohne einen Typ festzulegen.
Weitere Anwendungsbeispiele für satisfies, unter anderem zum Prüfen auf das Implementieren eines bestimmten Interfaces lassen sich dem zugehörigen Issue auf GitHub entnehmen.
Klarere Typen fĂĽr in
Im Zusammenspiel mit dem JavaScript-Operator in setzt TypeScript 4.9 auf ein weniger striktes Type Narrowing als bisher. Folgendes Codebeispiel aus dem TypeScript-Blog führte bisher zu einem Fehler, da TypeScript packageJSON als object zugeordnet hat, das die Property name nicht enthält:
interface Context {
packageJSON: unknown;
}
function tryGetPackageName(context: Context) {
const packageJSON = context.packageJSON;
// Check to see if we have an object.
if (packageJSON && typeof packageJSON === "object") {
// Check to see if it has a string name property.
if ("name" in packageJSON &&
typeof packageJSON.name === "string") {
// ~~~~
// error! Property 'name' does not exist on type 'object.
return packageJSON.name;
// ~~~~
// error! Property 'name' does not exist on type 'object.
}
}
return undefined;
}
Mit dem aktuellen Release stellt TypeScript fĂĽr den Ausdruck key in obj fĂĽr existierende SchlĂĽssel sicher, dass der Wert fĂĽr key entweder ein String, eine Zahl oder ein Symbol sein muss (string | number | symbol) und obj vom Typ object ist. Damit funktioniert obiges Codebeispiel fehlerfrei.
Weitere Neuerungen in TypeScript 4.9 sowie Informationen zu ein paar kleineren Performance-Verbesserungen lassen sich dem TypeSript-Blog entnehmen.
(rme)