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.

Lesezeit: 3 Min.
In Pocket speichern
vorlesen Druckansicht Kommentare lesen 2 Beiträge
Schreibmaschine, Tastatur, Keyboard, Digitalisierung

(Bild: , gemeinfrei)

Von
  • Rainald Menge-Sonnentag
Inhaltsverzeichnis

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.

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;

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.

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)