Programmiersprache TypeScript 4.9 prüft Voraussetzungen mit satisfies-Operator
Neben dem neuen Operator, der Bedingungen festlegt, ohne Typen durch zusätzliche Angaben einzuschränken, passt die Beta von TypeScript 4.9 den in-Operator an.
Microsoft hat die erste Beta von TypeScript 4.9 veröffentlicht. Der JavaScript-Aufsatz erhält im aktuellen Release mit satisfies
einen neuen Operator, um unterschiedliche Vorgaben für Expressions festzulegen. Außerdem bietet der in
-Operator klare Typzuweisungen für den Schlüssel und das Objekt.
Erfüllte Voraussetzungen
Der neue Operator satisfies
dient für unterschiedliche Typprüfungen in Ausdrücken. Er kann für Properties sowohl den passenden Namen als auch den passenden Typ als Bedingung festlegen, ohne dabei eine strikte Typvorgabe in der Deklaration zu erfordern. Das zugehörige Issue trägt den Titel "'satisfies' operator to ensure an expression matches some type".
Unter anderem lässt sich festlegen, dass Properties den passenden Namen haben, ohne dabei einen festen Typ vorzugeben wie in folgendem Beispiel aus dem Issue:
type Keys = 'a' | 'b' | 'c' | 'd';
const p = {
a: 0,
b: "hello",
c: true
// Fehler: 'd' aus 'Keys' fehlt
} satisfies Record<Keys, unknown>;
Die Vorgabe lässt sich über Partial
flexibler gestalten: Es legt fest, dass die Namen der Properties zwar aus der Bedingung stammen, aber nicht vollständig vorhanden sein müssen. Mit dem Zusatz würde obiges Beispiel somit keinen Fehler auslösen, aber folgendes:
type Keys = 'a' | 'b' | 'c' | 'd';
const p = {
a: 0,
b: "hello",
x: 8 // Fehler: 'x' ist nicht in 'Keys' vorhanden
} satisfies Partial<Record<Keys, unknown>>;
Mit satisfies
lässt sich zudem unter anderem umgekehrt festlegen, dass die Properties beliebige Namen tragen dürfen, ihre Werte aber einem bestimmten Typ entsprechen müssen. Zu den weiteren Bedingungen gehört das Implementieren eines bestimmten Interfaces:
type Movable = {
move(distance: number): void;
};
const car = {
start() { },
move(d) {
// d: number
},
stop() { }
} satisfies Moveable;
Passende Properties für den in-Operator
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.
Kein Vergleich für keine Zahl
Für den Spezialwert NaN
, der für Not a Number, also kein Zahlenwert steht, gelten Sonderregeln – nicht nur für TypeScript und JavaScript, sondern für alle Sprachen, die Gleitkommazahlen nach IEEE 754 implementieren. Die Spezifikation legt fest, dass alle Gleichheitschecks zu NaN
false
ergeben. Per Definition gilt dabei auch:
console.log(NaN == NaN) // false
console.log(NaN === NaN) // false
console.log(NaN != NaN) // true
console.log(NaN !== NaN) // true
NaN
ist also auch ungleich NaN
. Das kann zu einem Anfängerfehler führen, wenn Code die Prüfung auf NaN
mit einem !=
durchführt. Daher verbietet TypeScript ab sofort Gleich- 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)'?
}
Weitere Neuerungen in Version 4.9 lassen sich dem TypeScript-Blog entnehmen. Ende Oktober soll der erste Release Candidate erscheinen und das endgültige Release steht für den 15. November auf dem Plan.
(rme)