Programmiersprache: TypeScript 4.5 verzichtet doch auf ECMAScript-Module

Die ursprünglich für das Release geplante Anbindung an ESM-Module ist vorerst verschoben. Grund sind Bedenken bezüglich des sinnvollen Einsatzes.

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

(Bild: , gemeinfrei)

Von
  • Rainald Menge-Sonnentag

Microsoft hat planmäßig TypeScript 4.5 veröffentlicht. Das Release bringt vor allem Optimierungen unter der Haube mit und nimmt zwei geplante Neuerungen im ECMAScript-Standard vorweg, die private Felder und importierte Dateien betreffen.

Beim Start der Betaphase Anfang Oktober stand eine Erweiterung des Modulsystems auf dem Plan, um neben CommonJS (CJS) auch ECMAScript Modules (ESM) im Zusammenspiel mit Node.js zu verarbeiten. Allerdings hat das Team bereits beider Veröffentlichung des Release Candidate einen Rückzieher gemacht. Ein Grund dafür sind laut dem zugehörigen Issue auf GitHub noch zu fixende Bugs.

Schwerer wiegen darüber hinaus die Bedenken bezüglich der Usability. Das korrekte Verfassen von Paketen sei ohnehin schon schwierig genug, und der geplante node12-Modus würde zusätzliche Verwirrung stiften. Daher will das Team noch weiter an der Umsetzung arbeiten, um zu verhindern, dass Paket-Autoren die Module falsch verwenden und sich damit ins eigene Fleisch schneiden.

Die weiteren Features der Beta sind in der GA-Version enthalten. Das betrifft unter anderem die Heuristik, um Rekursionen zu erkennen, die potenziell unendlich laufen, und Typexpansionen, die sehr lange Laufzeit in Anspruch nehmen. Als Beispiel dient folgender Codeausschnitt aus dem TypeScript-Blog, der mit dem TrimLeft-Typ führende Leerzeichen aus einem String-ähnlichen Typ entfernt:

type TrimLeft<T extends string> =
    T extends ` ${infer Rest}` ? TrimLeft<Rest> : T;

// error: Type instantiation is excessively deep 
// and possibly infinite.
type Test = 
 TrimLeft<"                                                oops">;

Bisher löste der Code eine Fehlermeldung aufgrund der tiefen Rekursion mit den zahlreichen zu entfernenden Leerzeichen. Die Beispielfunktion ist jedoch endrekursiv in einem Zweig. TypeScript 4.5 entfernt neuerdings die endständigen Funktionsaufrufe, wenn ein Zweig des konditionalen Typs selbst wieder ein Conditional Type ist. Auf die Weise sind keine zusätzlichen Instanziierungen erforderlich, die den Speicherbedarf der rekursiven Funktion potenziell ins Unendliche treiben.

Ebenfalls neu ist der Awaited-Typ, der unter anderem für das Zusammenspiel mit await in async-Funktionen oder die .then()-Methode in Promise gedacht ist. Als Motivation diente wohl die Umsetzung von Promise.all(), wie folgendes Codebeispiel zeigt, das bisher ohne den Awaited-Typ zu einer Fehlermeldung führte:

declare function 
  MaybePromise<T>(value: T): T | Promise<T> | PromiseLike<T>;

async function doSomething(): Promise<[number, number]> {
    const result = await Promise.all([
        MaybePromise(100),
        MaybePromise(200)
    ]);

    // Error!
    //
    //    [number | Promise<100>, number | Promise<200>]
    //
    // is not assignable to type
    //
    //    [number, number]
    return result;
}

Weitere Beispiele und eine genauere Erklärung finden sich im zugehörigen Pull Request auf GitHub.

Der neue Parameter --preserveValueImports verhindert das automatische Entfernen von scheinbar nicht genutzten Importen. Als Beispiel führt der Blogbeitrag einen Codeschnipsel mit eval auf:

import { Animal } from "./animal.js";

eval("console.log(new Animal().isDangerous())");

Grundsätzlich ist der Einsatz von eval in TypeScript und JavaScript schon aus Sicherheitsgründen fragwürdig, aber das Beispiel demonstriert einen Fall, bei dem TypeScript womöglich einen Import zu Unrecht als überflüssig ansieht und entfernt, da es das in der Zeichenkette verwendete JavaScript-Modul nicht erkennt. Ähnliches gilt für das Zusammenspiel mit Frameworks wie Vue.js oder Svelte. Dort sind einige Importe für das Build-System nicht auf Anhieb als genutzt erkennbar, weil sie in script-Passagen eingebunden sind.

Zwei Neuerungen greifen ECMAScript-Vorschläge auf, die noch nicht im Standard existieren, aber geplant sind. Zum einen kann TypeScript überprüfen, ob ein Objekt ein privates Feld enthält, das in der aktuellen Klasse definiert ist. Das zugehörige ECMA-Proposal trägt den Titel "Ergonomic brand checks for Private Fields" (in etwa übersetzbar als "Ergonomische Sortenüberprüfung für private Felder"). Über die privaten Felder lässt sich prüfen, ob es sich tatsächlich um eine Instanz der Klasse handelt, da sie nur in dem Fall existieren.

Außerdem können Entwicklerinnen und Entwickler die ebenfalls für ECMAScript vorgesehenen Import Assertions in TypeScript 4.5 nutzen. Sie stellen sicher, dass eine importierte Datei ein bestimmtes Format hat:

import obj from "./something.json" assert { type: "json" };

Das Build-System überprüft dabei nur das angegebene Format und nicht die tatsächlichen Inhalte. Für Letztere liegt die Verantwortung beim Browser beziehungsweise der Runtime.

Weitere Neuerungen in TypeScript 4.5 wie die erweiterte Anbindung an JSDoc und die Snippet-Autovervollständigung für Klassenmethoden lassen sich dem Entwicklungsblog bei Microsoft entnehmen. Das Release steht über NuGet zur Verfügung oder lässt sich mit npm install typescript installieren.

(rme)