Vor einigen Tagen haben wir die Verfügbarkeit unseres Release Candidate (RC) von TypeScript 3.4 angekündigt. Wir hoffen, Feedback und frühe Ausgaben zu sammeln, um sicherzustellen, dass unsere endgültige Version einfach zu erfassen und sofort zu verwenden ist.
Um mit der Verwendung des RC zu beginnen, können Sie ihn über NuGet herunterladen oder npm mit dem folgenden Befehl verwenden:
npm install -g typescript@rc
Sie können auch Editor-Unterstützung von erhalten
Lassen Sie uns untersuchen, was in 3.4 neu ist!
Dieser Artikel in unserem Blog.Schnellere nachfolgende Builds mit dem Flag --incremental
Da TypeScript-Dateien kompiliert werden, wird ein Zwischenschritt zwischen dem Schreiben und Ausführen Ihres Codes eingeführt. Eines unserer Ziele ist es, die Bauzeit bei Änderungen an Ihrem Programm zu minimieren. Eine Möglichkeit, dies zu tun, besteht darin, TypeScript im --watch
Modus --watch
. Wenn sich eine Datei im --watch
Modus ändert, kann TypeScript --watch
des zuvor erstellten Abhängigkeitsdiagramms Ihres Projekts ermitteln, welche Dateien möglicherweise betroffen sind und erneut überprüft und möglicherweise erneut ausgegeben werden müssen. Dies kann eine vollständige Typprüfung und erneute Ausgabe vermeiden, was kostspielig sein kann.
Es ist jedoch unrealistisch zu erwarten, dass alle Benutzer einen tsc --watch
Prozess über Nacht tsc --watch
, um morgen früh schnellere Builds zu erhalten. Was ist mit kalten Builds? In den letzten Monaten haben wir daran gearbeitet, ob es eine Möglichkeit gibt, die entsprechenden Informationen aus dem --watch
Modus in einer Datei zu speichern und von Build zu Build zu verwenden.
TypeScript 3.4 führt ein neues Flag namens --incremental
das TypeScript --incremental
, Informationen über das Projektdiagramm aus der letzten Kompilierung zu speichern. --incremental
TypeScript das nächste Mal mit --incremental
aufgerufen --incremental
, werden diese Informationen verwendet, um die kostengünstigste Methode zur Typprüfung und Ausgabe von Änderungen an Ihrem Projekt zu ermitteln.
Standardmäßig tsc
TypeScript bei diesen Einstellungen beim Ausführen von .tsbuildinfo
in unserem Ausgabeverzeichnis ( ./lib
) nach einer Datei mit dem Namen .tsbuildinfo
. Wenn ./lib/.tsbuildinfo
nicht vorhanden ist, wird es generiert. In diesem Fall versucht tsc
, diese Datei zu verwenden, um unsere Ausgabedateien schrittweise zu überprüfen und zu aktualisieren.
Diese .tsbuildinfo
Dateien können sicher gelöscht werden und haben zur Laufzeit keine Auswirkungen auf unseren Code. Sie dienen lediglich dazu, die Kompilierung zu beschleunigen. Wir können sie auch beliebig --tsBuildInfoFile
und sie mit dem Flag --tsBuildInfoFile
beliebigen Stelle --tsBuildInfoFile
.
Solange niemand anderes versucht, in dieselbe Cache-Datei zu schreiben, sollten wir in der Lage sein, schnellere inkrementelle Cold-Builds zu genießen.
Zusammengesetzte Projekte
Ein Teil der Absicht bei zusammengesetzten Projekten ( tsconfig.json
s mit zusammengesetztem composite
auf true
) besteht darin, dass Referenzen zwischen verschiedenen Projekten inkrementell erstellt werden können. Daher erstellen zusammengesetzte Projekte immer .tsbuildinfo
Dateien.
outFile
Wenn outFile
verwendet wird, basiert der Name der Build-Informationsdatei auf dem Namen der Ausgabedatei. Wenn unsere JavaScript-Ausgabedatei beispielsweise ./output/foo.js
--incremental
, generiert TypeScript unter dem Flag --incremental
die Datei ./output/foo.tsbuildinfo
. Wie oben kann dies mit dem Flag --tsBuildInfoFile
gesteuert werden.
Das --incremental
Dateiformat und die Versionierung
Während die von --incremental
generierte Datei JSON ist, --incremental
die Datei nicht von einem anderen Tool verwendet werden. Wir können keine Garantie für die Stabilität des Inhalts geben. Unsere derzeitige Richtlinie lautet, dass eine Version von TypeScript .tsbuildinfo
Dateien, die aus einer anderen Version generiert wurden, nicht versteht.
Verbesserungen für ReadonlyArray
und readonly
Tupel
TypeScript 3.4 erleichtert die Verwendung von schreibgeschützten Array-ähnlichen Typen ein wenig.
Eine neue Syntax für ReadonlyArray
Der ReadonlyArray
Typ beschreibt Array
, aus denen nur gelesen werden kann. Jede Variable mit einem Handle für ein ReadonlyArray
kann keine Elemente des Arrays hinzufügen, entfernen oder ersetzen.
function foo(arr: ReadonlyArray<string>) { arr.slice();
Während es oft eine gute Praxis ist, ReadonlyArray
über Array
zum Zweck der Absicht zu verwenden, war es oft ein Schmerz, da Arrays eine schönere Syntax haben. Insbesondere ist number[]
eine Kurzversion von Array<number>
, ebenso wie Date[]
eine Kurzform für Array<Date>
.
TypeScript 3.4 führt eine neue Syntax für ReadonlyArray
, die einen neuen readonly
Modifikator für Array-Typen verwendet.
function foo(arr: readonly string[]) { arr.slice();
readonly
Tupel
TypeScript 3.4 readonly
außerdem eine neue Unterstützung für readonly
Tupel. Wir können jedem readonly
Schlüsselwort readonly
, um es zu einem readonly
Tupel zu machen, ähnlich wie wir es jetzt mit der Array-Kurzschrift-Syntax tun können. Wie zu erwarten ist, erlauben readonly
Tupel im Gegensatz zu normalen Tupeln, in die Slots geschrieben werden können, nur das Lesen von diesen Positionen aus.
function foo(pair: readonly [string, string]) { console.log(pair[0]);
Genauso wie gewöhnliche Tupel Typen sind, die sich von Array
aus erstrecken - ein Tupel mit Elementen vom Typ T
1
, T
2
, ... T
n
erstreckt sich von Array<
T
1
| T
2
| ... T
n
>
- readonly
Tupel sind Typen, die sich von ReadonlyArray
. Ein readonly
Tupel mit den Elementen T
1
, T
2
, ... T
n
erstreckt sich also von ReadonlyArray<
T
1
| T
2
| ... T
n
>
.
readonly
zugeordnete readonly
und readonly
Arrays
In früheren Versionen von TypeScript haben wir zugeordnete Typen so verallgemeinert, dass sie bei Array-ähnlichen Typen unterschiedlich funktionieren. Dies bedeutete, dass ein zugeordneter Typ wie Boxify
auf Arrays und Tupeln gleichermaßen Boxify
konnte.
interface Box<T> { value: T } type Boxify<T> = { [K in keyof T]: Box<T[K]> }
Leider waren zugeordnete Typen wie der Dienstprogrammtyp Readonly
und Readonly
keine Readonly
.
In TypeScript 3.4 readonly
der readonly
Modifikator in einem zugeordneten Typ automatisch Array-ähnliche Typen in die entsprechenden readonly
Gegenstücke.
In ähnlicher Weise könnten Sie einen Dienstprogrammtyp wie den beschreibbaren zugeordneten Typ schreiben, der die readonly
entfernt und readonly
Array-Container wieder in ihre veränderlichen Entsprechungen konvertiert.
type Writable<T> = { -readonly [K in keyof T]: T[K] }
Vorsichtsmaßnahmen
Trotz seines Erscheinungsbilds kann der readonly
nur für die Syntax von readonly
und readonly
verwendet werden. Es ist kein Allzweckoperator.
let err1: readonly Set<number>;
const
Behauptungen
Beim Deklarieren einer veränderlichen Variablen oder Eigenschaft erweitert TypeScript häufig die Werte, um sicherzustellen, dass wir später Dinge zuweisen können, ohne einen expliziten Typ zu schreiben.
let x = "hello";
Technisch gesehen hat jeder Literalwert einen Literaltyp. Oben wurde der Typ "hello"
auf die Typzeichenfolge erweitert, bevor auf einen Typ für x
.
Eine alternative Sichtweise könnte sein, zu sagen, dass x
den ursprünglichen Literaltyp "hello"
und dass wir später nicht "world"
wie "hello"
zuweisen können:
let x: "hello" = "hello";
In diesem Fall scheint das extrem, kann aber in anderen Situationen nützlich sein. Beispielsweise erstellen TypeScripters häufig Objekte, die in diskriminierten Gewerkschaften verwendet werden sollen.
type Shape = | { kind: "circle", radius: number } | { kind: "square", sideLength: number } function getShapes(): readonly Shape[] { let result = [ { kind: "circle", radius: 100, }, { kind: "square", sideLength: 50, }, ];
Die Veränderlichkeit ist eine der besten Heuristiken der Absicht, mit der TypeScript bestimmen kann, wann sie erweitert werden muss (anstatt unser gesamtes Programm zu analysieren).
Wie wir im letzten Beispiel gesehen haben, sind die Eigenschaften von JavaScript leider standardmäßig veränderbar. Dies bedeutet, dass die Sprache häufig unerwünschte Typen erweitert und an bestimmten Stellen explizite Typen erfordert.
function getShapes(): readonly Shape[] {
Bis zu einem gewissen Punkt ist dies in Ordnung, aber da unsere Datenstrukturen immer komplexer werden, wird dies umständlich.
Um dies zu lösen, führt TypeScript 3.4 ein neues Konstrukt für Literalwerte ein, das als const
assertions bezeichnet wird. Seine Syntax ist eine Typzusicherung mit const
anstelle des const
(z 123 as const
B. 123 as const
). Wenn wir neue wörtliche Ausdrücke mit const
Aussagen konstruieren, können wir der Sprache signalisieren, dass
- Es sollten keine Literaltypen in diesem Ausdruck erweitert werden (z. B. kein Übergang von
"hello"
zu string
). - Objektliterale erhalten
readonly
Eigenschaften - Array-Literale werden zu
readonly
Tupeln
Außerhalb von .tsx
Dateien kann auch die Syntax für die Assertion von spitzen Klammern verwendet werden.
Diese Funktion bedeutet häufig, dass Typen, die ansonsten nur verwendet würden, um dem Compiler auf Unveränderlichkeit hinzuweisen, häufig weggelassen werden können.
Beachten Sie, dass oben keine Typanmerkungen erforderlich sind. Mit der const
Zusicherung konnte TypeScript den spezifischsten Typ des Ausdrucks verwenden.
Vorsichtsmaßnahmen
Zu beachten ist, dass const
Zusicherungen nur sofort auf einfache Literalausdrücke angewendet werden können.
Eine andere Sache, die Sie beachten sollten, ist, dass const
Kontexte einen Ausdruck nicht sofort in eine vollständig unveränderliche konvertieren.
let arr = [1, 2, 3, 4]; let foo = { name: "foo", contents: arr, }; foo.name = "bar";
Typprüfung für globalThis
Es kann überraschend schwierig sein, auf Werte im globalen Bereich zuzugreifen oder diese zu deklarieren, möglicherweise weil wir unseren Code in Modulen schreiben (deren lokale Deklarationen standardmäßig nicht auslaufen) oder weil wir möglicherweise eine lokale Variable haben, die den Namen von schattiert ein globaler Wert. In verschiedenen Umgebungen gibt es verschiedene Möglichkeiten, auf den globalen Bereich zuzugreifen - global
in Knoten, window
, self
oder frames
im Browser oder an bestimmten Orten außerhalb des strengen Modus. Nichts davon ist offensichtlich und führt häufig dazu, dass Benutzer sich nicht sicher sind, ob sie den richtigen Code schreiben.
TypeScript 3.4 globalThis
Unterstützung für die Typprüfung des neuen globalThis
ECMAScript - eine globale Variable, die sich auf den globalen Bereich bezieht. Im Gegensatz zu den oben genannten Lösungen bietet globalThis
eine Standardmethode für den Zugriff auf den globalen Bereich, der in verschiedenen Umgebungen verwendet werden kann.
globalThis
auch widerspiegeln, ob eine globale Variable als const
deklariert wurde oder nicht, indem sie beim Zugriff als readonly
Eigenschaft behandelt wird.
const answer = 42; globalThis.answer = 333333;
Es ist wichtig zu beachten, dass TypeScript beim Kompilieren auf ältere Versionen von ECMAScript keine Verweise auf globalThis
transformiert. Sofern Sie nicht auf immergrüne Browser abzielen (die bereits globalThis
), möchten Sie möglicherweise stattdessen eine geeignete Polyfüllung verwenden.
In benannte Parameter konvertieren
Manchmal werden Parameterlisten unhandlich.
function updateOptions( hue?: number, saturation?: number, brightness?: number, positionX?: number, positionY?: number positionZ?: number) {
Im obigen Beispiel ist es für einen Aufrufer viel zu einfach, die Reihenfolge der angegebenen Argumente zu verwechseln. Ein gängiges JavaScript-Muster besteht darin, stattdessen ein „Optionsobjekt“ zu verwenden, sodass jede Option explizit benannt wird und die Reihenfolge keine Rolle spielt. Dies emuliert eine Funktion, die andere Sprachen als "benannte Parameter" bezeichnet haben.
interface Options { hue?: number, saturation?: number, brightness?: number, positionX?: number, positionY?: number positionZ?: number } function updateOptions(options: Options = {}) {
Das TypeScript-Team arbeitet nicht nur an einem Compiler, sondern bietet auch die Funktionen, die Editoren für umfangreiche Funktionen wie Vervollständigungen, Definitionen und Refactorings verwenden. In TypeScript 3.4 hat unsere Praktikantin Gabriela Britto ein neues Refactoring implementiert, um vorhandene Funktionen für die Verwendung dieses Musters mit benannten Parametern zu konvertieren.

Obwohl wir den Namen der Funktion bis zu unserer endgültigen Version 3.4 ändern können und wir glauben, dass möglicherweise Platz für einen Teil der Ergonomie vorhanden ist, würden wir uns freuen, wenn Sie die Funktion ausprobieren und uns Ihr Feedback geben.
Änderungen brechen
Auf oberster Ebene ist this
jetzt eingegeben
Der Typ der obersten Ebene wird jetzt als Typ von typeof globalThis
anstelle von any
typeof globalThis
. Infolgedessen erhalten Sie möglicherweise Fehler beim Zugriff auf unbekannte Werte unter noImplicitAny
.
Beachten Sie, dass der unter noImplicitThis
kompilierte Code hier keine Änderungen erfährt.
Propagierte generische Typargumente
In bestimmten Fällen kann die verbesserte Inferenz von TypeScript 3.4 zu generischen Funktionen führen, anstatt zu Funktionen, die ihre Einschränkungen übernehmen und zurückgeben (normalerweise {}
).
declare function compose<T, U, V>(f: (arg: T) => U, g: (arg: U) => V): (arg: T) => V; function list<T>(x: T) { return [x]; } function box<T>(value: T) { return { value }; } let f = compose(list, box); let x = f(100)
Eine explizite Typanmerkung auf x
kann den Fehler beseitigen.
Was kommt als nächstes?
TypeScript 3.4 ist unsere erste Version mit einem Iterationsplan , der unsere Pläne für diese Version umreißt und mit unserer 6-Monats-Roadmap übereinstimmen soll . Sie können beide und unsere Roadmap-Seite für fortlaufende Funktionen für alle anstehenden Arbeiten im Auge behalten.
Im Moment freuen wir uns darauf, von Ihren Erfahrungen mit dem RC zu hören. Probieren Sie es jetzt aus und teilen Sie uns Ihre Gedanken mit!