Programmiersprache: TypeScript 4.6 gibt sich flexibler beim Konstruktor

Der Konstruktor darf neuerdings Code vor dem Elternaufruf mit super enthalten. AuĂźerdem bringt das Release einige Verbesserungen bei der Typuntersuchung mit.

In Pocket speichern vorlesen Druckansicht 3 Kommentare lesen
Schreibmaschine, Tastatur, Keyboard, Digitalisierung

(Bild: , gemeinfrei)

Lesezeit: 2 Min.
Inhaltsverzeichnis

Knapp eine Woche nach dem geplanten Termin ist die erste Beta von TypeScript 4.6 erschienen. Das Release bringt vor allem Ă„nderungen unter der Haube mit, die auf eine bessere Analyse von Typen zielen. AuĂźerdem ist es weniger streng mit dem Konstruktor von Kindobjekten, die den Konstruktor des Elternobjekts aufrufen.

TypeScript verbietet wie JavaScript aus gutem Grund im Konstruktor den Zugriff auf this vor dem Aufruf von super(), da die Elternklasse die Inhalte des Objekts dort initialisiert. Allerdings war Microsofts Programmiersprache bisher wohl etwas zu strikt mit den Regeln und hat vor dem Aufruf des elterlichen Konstruktors jeden Code verboten, auch wenn dieser nicht auf das Objekt selbst ĂĽber this zugreift.

Das ändert sich mit dem aktuellen Release nach langer Vorarbeit: Der zugehörige Pull Request ist drei Jahre alt und hat kurz vor der Umsetzung einen Geburtstagskuchen erhalten. Mit der Implementierung ist nun Code vor super erlaubt, wobei TypeScript sicherstellt, dass er keinen Zugriff auf das Objekt durch this enthält.

Die Änderungen unter der Haube beziehen sich vor allem auf die Typzuordnung beziehungsweise -prüfung. So leitet die Programmiersprache bei der Kombination aus Indexed Access Types mit einer Map für den Indexzugriff den konkreten Typ her. Bisher hat sie alle in der Map definierten Typen als mögliche Zuordnung zugewiesen, wie folgendes Beispiel aus dem TypeScript-Blog zeigt:

interface TypeMap {
    "number": number;
    "string": string;
    "boolean": boolean;
}

type UnionRecord<P extends keyof TypeMap> = { [K in P]:
    {
        kind: K;
        v: TypeMap[K];
        f: (p: TypeMap[K]) => void;
    }
}[P];

function processRecord<K extends keyof TypeMap>(record: 
                                                UnionRecord<K>) {
    record.f(record.v);
}

processRecord({
    kind: "string",
    v: "hello!",

    // 'val' used to implicitly have the type 
    // 'string | number | boolean',
    // but now is correctly inferred to just 'string'.
    f: val => {
        console.log(val.toUpperCase());
    }
})

Außerdem bringt TypeScript 4.6 eine verbesserte Kontrollflussanalyse für abhängige Rest Parameter, bei denen der Typ eines Parameters von dem davor stehenden abhängt:

function func(...args: ["str", string] | ["num", number])

Wenn der erste Parameter "str" ist, ist der zweite ein String. Wenn der erste Paramter aber "num" ist, ist der zweite eine number. TypeScript nutzt dieses Wissen nun im weiteren Code und kennt in Blöcken, die den ersten Parameter überprüfen, den Typ des zweiten, wie in folgendem Beispiel aus dem TypeScript-Blog:

type Func = (...args: ["a", number] | ["b", string]) => void;

const f1: Func = (kind, payload) => {
    if (kind === "a") {
        payload.toFixed();  // 'payload' narrowed to 'number'
    }
    if (kind === "b") {
        payload.toUpperCase();  // 'payload' narrowed to 'string'
    }
};

f1("a", 42);
f1("b", "hello");

Zur tieferen Analyse von Tools über mit dem --generateTrace-Flag erstellte Ausgaben hat das Team einen Trace-Analyzer veröffentlicht, der als eigenständiges Projekt auf GitHub verfügbar ist.

Weitere Neuerungen in der Beta zu Version 4.6 wie die verbesserte ĂśberprĂĽfung der Tiefe von rekursiven Instanziierungen lassen sich dem TypeScript-Blog entnehmen. Das fertige Release ist fĂĽr den 22. Februar geplant.

(rme)