TypeScript 3.0

TypeScript 3.0! Ja, er ist herausgekommen und es gibt wirklich viele Neuerungen. Unter dem Schnitt finden Sie eine detaillierte Beschreibung aller neuesten Innovationen, einschließlich des Erstellungsmodus, eines neuen unbekannten Typs, wesentlicher Änderungen an der API, Leistungsverbesserungen und vielem mehr. Jetzt mitmachen!



TypeScript 3.0 veröffentlicht! Ein neuer Meilenstein auf dem Weg zur Entwicklung von TypeScript, einem Assistenten für alle JavaScript-Benutzer, hat begonnen.

Wenn Sie mit TypeScript nicht vertraut sind, ist es noch nicht zu spät, dies jetzt zu erfahren! TypeScript ist eine JavaScript-Erweiterung, die für die Verwendung in der modernen Version dieser Sprache statischer Typen entwickelt wurde. Der TypeScript-Compiler liest TypeScript-Code, der insbesondere Typdeklarationen und Typanmerkungen enthält, und erzeugt sauberen, einfach zu lesenden JavaScript-Code, in dem diese Konstrukte transformiert und gelöscht werden. Der resultierende Code wird in jeder Laufzeitumgebung ausgeführt, die dem ECMAScript-Standard entspricht, z. B. in Ihrem bevorzugten Browser oder auf der Node.js-Serverplattform.

Die Verwendung einer solchen Umgebung bedeutet, dass der Code vor dem Start durch Benutzer auf Fehler oder Tippfehler analysiert wird. Die Vorteile sind jedoch nicht darauf beschränkt. Mit all diesen Informationen und Analyseergebnissen verbessert TimeScript die Benutzerfreundlichkeit, indem es automatische Code-Vervollständigungs- und Navigationswerkzeuge wie Alle Referenzen suchen, Zur Definition gehen und in Ihrem bevorzugten Editor umbenennen bereitstellt. .

Folgen Sie dem Link, um mit der Sprache zu beginnen und weitere Informationen zu erhalten. Wenn Sie TypeScript 3.0 jetzt ausprobieren möchten, können Sie es von NuGet oder über npm herunterladen, indem Sie es eingeben

npm install -g typescript 

Darüber hinaus ist Unterstützung in den folgenden Editoren verfügbar:


Andere Editoren werden nach ihrem eigenen Zeitplan aktualisiert, aber bald werden sie alle eine hervorragende TypeScript-Unterstützung haben.

Version 3.0 Übersicht


Nach der Veröffentlichung von TypeScript 2.0 gaben wir einen kurzen Überblick über den Beitrag früherer Versionen zum aktuellen Status. Zwischen den Versionen von TypeScript 1.0 und 2.0 umfasst die Sprache Union-Typen, Type Guards, Unterstützung für den modernen ECMAScript-Standard, Typ-Aliase, JSX-Unterstützung sowie wörtliche und polymorphe Typen this Typen. Wenn Sie TypeScript 2.0-Typen, die nicht null-fähig sind, Kontrollflussanalyse, Unterstützung für markierte Gewerkschaften, diese Typen und ein vereinfachtes Modell für den Empfang von .d.ts Dateien .d.ts , können wir sagen, dass dieser Zeitraum die Grundlagen vollständig bestimmt hat TypeScript funktioniert.

Was wurde seitdem getan? Was hat uns zu TypeScript 3.0 geführt, zusätzlich zu den neuen Funktionen des ECMAScript-Standards wie asynchrone / await asynchrone Funktionen, Generatoren und dem Rest / Spread-Operator?

TypeScript 2.1 wurde zur grundlegenden Version, die ein statisches Metaprogrammierungsmodell in JavaScript einführte. Schlüsselanforderung ( keyof ), keyof ( T[K] ) und Arten von zugeordneten Objekten ( { [K in keyof T]: } T[K]} ) - Dies ist eine Liste von Tools, mit denen die React-, Ember-Bibliotheken effektiver modelliert wurden. Lodash und andere.

In den Versionen TypeScript 2.2 und 2.3 wurden Mixin-Klassenvorlagen, der object (der ein Objekt darstellt, das kein Grundelement ist) und Standardwerte für generische Typen unterstützt. Diese Funktionen wurden in einer Reihe von Projekten wie Angular Material und Polymer verwendet. Darüber hinaus wurde mit TypeScript 2.3 die Möglichkeit eingeführt, this Typen zu checkJs , sodass die Sprache gut mit Bibliotheken wie Vue zusammenarbeitet. checkJs Flag checkJs wurde checkJs , damit Typen in JavaScript-Dateien überprüft werden können.

TypeScript 2.4 und 2.6 setzen die Geschichte fort, den Schweregrad der Funktionsüberprüfung zu erhöhen, die mit einigen der ältesten Überprüfungen unseres Typsystems verbunden ist. Das Flag --strictFunctionTypes wurde eingeführt, wodurch die Kontravarianz von Parametern --strictFunctionTypes wurde. In Release 2.7 hat sich der Trend zur Strenge fortgesetzt und wurde in der Validierung in Klassen mit dem Flag --strictPropertyInitialization .

TypeScript 2.8 führt bedingte Typen ein, ein leistungsstarkes Tool zum statischen Ausdrücken typbasierter Entscheidungen, und Release 2.9 verallgemeinert den Operator keyof und vereinfacht den Import für Typen.

Und das bringt uns zu TypeScript 3.0! Trotz der neuen Ganzzahl in der Zahl hat sich in Release 3.0 wenig geändert (was ein sehr einfaches Update impliziert). Es bietet eine neue flexible und skalierbare Methode zur Strukturierung von Projekten, eine leistungsstarke neue Unterstützung für die Arbeit mit Parameterlisten, neue Typen für die Bereitstellung expliziter Überprüfungen, eine verbesserte JSX-Unterstützung, eine wesentlich benutzerfreundlichere Fehlerdiagnose und vieles mehr.

Was gibt's Neues?


  • Projektverknüpfungen
    • --build
    • Output Structure Management
    • Zukunftspläne
  • Abrufen und Verteilen von Parameterlisten mithilfe von Tupeln
  • Neue Tupeltypfunktionen
  • Typ unknown
  • Verbesserte Fehlerdiagnose und Benutzerumgebung
    • Zugehörige Fehlerbereiche
    • Verbesserte Diagnose und Fehlerbehandlung
  • Unterstützung für die Eigenschaft defaultProps in JSX
  • Anweisungen /// <reference lib="..." />
  • Verbesserung der Editorgeschwindigkeit
    • Refactoring benannter Importanweisungen
    • Ende Tag Ende und Umrissrahmen
    • Schnelle Korrekturen für nicht erreichbaren Code und nicht verwendete Tags
  • Kritische Veränderungen
    • unknown ist ein reservierter Typname
    • API-kritische Änderungen

Projektverknüpfungen


Sehr oft müssen Sie zum Erstellen einer Bibliothek oder Anwendung mehrere Schritte ausführen. Angenommen, Ihre Codebasis enthält die Verzeichnisse src und test . Angenommen, Sie haben einen Clientordner, in dem der Code des Clientteils der Anwendung gespeichert ist, und einen Serverordner, der den Serverteilcode auf der Node.js-Plattform enthält, und jeder von ihnen nimmt einen Teil des Codes aus dem shared Ordner auf. Vielleicht verwenden Sie das sogenannte „Single Repository“ und haben viele Projekte, die komplex voneinander abhängig sind.

Eine der wichtigsten Funktionen, an denen wir bei der Veröffentlichung von TypeScript 3.0 gearbeitet haben, hieß "Projektlinks" und soll die Arbeit mit solchen Skripten vereinfachen.

Dank Projektlinks können einige TypeScript-Projekte von anderen abhängen. Insbesondere dürfen tsconfig.json Dateien auf andere tsconfig.json Dateien tsconfig.json . Das Definieren dieser Abhängigkeiten erleichtert das Aufteilen des Codes in kleinere Projekte, da der TypeScript-Compiler (und seine Tools) die Möglichkeit erhalten, die Baugruppenreihenfolge und -struktur der Ausgabe zu verstehen. Dies bedeutet, dass die Montage schneller und schrittweise (schrittweise) ausgeführt wird. Transparente Navigation, Bearbeitung und Umgestaltung für verschiedene Projekte werden unterstützt. Da TypeScript 3.0 die Grundlage für das Projekt bildet und eine API bereitstellt, sollte jedes Build-Tool dies bereitstellen können.

Wie sieht es aus?


Hier ist eine tsconfig.json Datei, die als einfaches Beispiel Links zu Projekten enthält.

 // ./src/bar/tsconfig.json { "compilerOptions": { // Needed for project references. "composite": true, "declaration": true, // Other options... "outDir": "../../lib/bar", "strict": true, "module": "esnext", "moduleResolution": "node", }, "references": [ { "path": "../foo" } ] } 

Es hat zwei neue Felder: composite und references .

Das references verweist einfach auf andere tsconfig.json Dateien (oder die Ordner, in denen sie enthalten sind). Jeder Link hier ist einfach ein Objekt mit einem path („Pfad“) und teilt dem TypeScript-Compiler mit, dass Sie zum Erstellen dieses Projekts zuerst ein anderes Projekt erstellen müssen, auf das es verweist.

Anscheinend hat das composite Feld die gleiche Bedeutung. Das composite Feld stellt sicher, dass bestimmte Parameter aktiviert sind, die es jedem davon abhängigen Projekt ermöglichen, darauf zu verweisen und es in inkrementelle Builds aufzunehmen. Die Fähigkeit, intelligent und schrittweise zu erstellen, ist wichtig, da einer der Hauptgründe, warum Sie ein Projekt abbrechen können, die Erstellungsgeschwindigkeit ist.

Wenn das front-end Projekt beispielsweise vom shared shared Projekt abhängt und vom Kern shared wird, helfen unsere APIs, die sich auf Projektverknüpfungen beziehen, Änderungen im Kern zu identifizieren, erfassen sie jedoch nur dann wieder, wenn sich die vom core erzeugten Typen geändert haben (d. H. .d.ts Dateien). Dies bedeutet, dass eine Änderung des Kerns nicht zu einem globalen Zusammenbau aller Projekte führt. Aus diesem Grund bewirkt das Setzen des composite Flags auch das Setzen des declaration .

- Erstellungsmodus


TypeScript 3.0 führt eine Reihe von APIs für Projektreferenzen ein, damit andere Tools diese schnelle inkrementelle Erstellungsmethode bereitstellen können. Insbesondere das gulp-typescript-Plugin verwendet diese APIs bereits! So werden spätere Links zu Projekten in die Assembly-Orchestratoren Ihrer Wahl integriert.

Für viele einfache Anwendungen und Bibliotheken ist es jedoch ratsam, keine externen Tools zu verwenden. Aus diesem Grund setzt der Befehl tsc jetzt ein neues Flag --build .

Der tsc --build (oder sein Alias tsc -b ) nimmt eine Reihe von Projekten und erstellt sie sowie erstellte abhängige Projekte. Wenn Sie den neuen Erstellungsmodus verwenden, muss zunächst das Flag --build gesetzt werden, und es kann mit einigen anderen Flags kombiniert werden:
  • --verbose : Zeigt jeden Schritt an, der für den Erstellungsprozess erforderlich ist.
  • --dry : --dry ohne Ausgabedateien zu generieren (nützlich in Verbindung mit der Option --verbose ).
  • –clean : –clean , Ausgabedateien zu löschen, die der angegebenen Eingabe entsprechen.
  • --force : --force vollständige, nicht inkrementelle Erstellung des Projekts.

Output Structure Management


Ein subtiler, aber unglaublich nützlicher Vorteil von Projektreferenzen ist die logische Fähigkeit, Eingabedateien entsprechenden Ausgabedateien zuzuordnen.

Wenn Sie jemals versucht haben, die Client- und Serverteile der Anwendung zu trennen, können Probleme bei der Verwaltung der Ausgabestruktur auftreten.

Wenn sich beispielsweise client / index.ts und server / index.ts für die folgenden Projekte auf shared / index.ts beziehen:



... wenn wir dann versuchen, Client- und Serverprojekte zu erstellen, erhalten wir ...



…und nicht…



Beachten Sie, dass wir nach dem Build Kopien des freigegebenen Ordners sowohl auf dem Client als auch auf dem Server erhalten haben. Wir haben zusätzliche Zeit für das zweimalige Erstellen der gemeinsam genutzten Assembly aufgewendet und lib / client / client und lib / server / server eine unerwünschte Verschachtelung hinzugefügt.

Das Problem ist, dass TypeScript eifrig nach .ts-Dateien sucht und versucht, diese in diese Zusammenstellung aufzunehmen. Im Idealfall sollte TypeScript verstanden haben, dass diese Dateien nicht an der Assembly in derselben Kompilierung teilnehmen sollten, sondern stattdessen in den .d.ts-Dateien nach Typinformationen suchen.

Das Erstellen der Datei tsconfig.json für Shared führt genau zu diesem Ergebnis. Es signalisiert dem TypeScript-Compiler:

  1. dass das gemeinsam genutzte Projekt unabhängig erstellt werden muss
  2. und dass wir beim Importieren von ../shared nach .d.ts-Dateien in seinem Ausgabeverzeichnis suchen sollten.

Dadurch wird vermieden, dass eine doppelte Assembly ausgeführt wird und versehentlich alle freigegebenen Inhalte eingeschlossen werden.

Zukunftspläne


Um ein tieferes Verständnis der Design-Links und der Möglichkeiten ihrer Verwendung zu erhalten, lesen Sie diese im Tracker dieser Version ausführlicher. In naher Zukunft werden wir eine Dokumentation zu Projektverknüpfungen und zum Erstellungsmodus erstellen.

Wir bemühen uns, dass Autoren anderer Programmierwerkzeuge Verweise auf Projekte beibehalten und die Bearbeitungsumgebung in Bezug auf diese Funktion weiter verbessern können. Wir möchten sicherstellen, dass die Arbeit mit Projektverknüpfungen genauso reibungslos funktioniert wie die Entwicklung von Code mit einer einzigen tsconfig.json-Datei. Wenn Sie irgendwann Projektlinks verwenden, sind wir für jedes Feedback dankbar.

Abrufen und Verteilen von Parameterlisten mithilfe von Tupeln


Wir halten dies oft für selbstverständlich, aber mit JavaScript können wir Parameterlisten als erstklassige Werte betrachten - entweder mit Argumenten oder mit Parametern vom Typ rest (z. B. ... rest).

 function call(fn, ...args) { return fn(...args); } 

Beachten Sie, dass der Aufruf für Funktionen mit einer beliebigen Anzahl von Parametern funktioniert. Im Gegensatz zu anderen Sprachen zwingt uns JavaScript nicht, call0, call1, call2 usw. wie folgt zu definieren:

 function call0(fn) { return fn(); } function call1(fn, param1) { return fn(param1); } function call2(fn, param1, param2) { return fn(param1, param2); } function call3(fn, param1, param2, param3) { return fn(param1, param2, param3); } 

Leider gab es für einige Zeit keine gute Möglichkeit, dies in TypeScript auszudrücken, ohne eine endliche Anzahl von Überladungen zu deklarieren:

 // TODO (billg): 5 overloads should *probably* be enough for anybody? function call<T1, T2, T3, T4, R>(fn: (param1: T1, param2: T2, param3: T3, param4: T4) => R, param1: T1, param2: T2, param3: T3, param4: T4): R function call<T1, T2, T3, R>(fn: (param1: T1, param2: T2, param3: T3) => R, param1: T1, param2: T2, param3: T3): R function call<T1, T2, R>(fn: (param1: T1, param2: T2) => R, param1: T1, param2: T2): R function call<T1, R>(fn: (param1: T1) => R, param1: T1): R; function call<R>(fn: () => R, param1: T1): R; function call(fn: (...args: any[]) => any, ...args: any[]) { return fn(...args); } 

Puh! Ein weiterer Tod mit tausend Überladungen! Oder mindestens so viele Überlastungen, wie Benutzer benötigen.

Mit TypeScript 3.0 können Sie solche Szenarien besser simulieren, da jetzt Parameter des Resttyps universell sein können und ihr Typ als Tupel definiert ist. Anstatt jede dieser Überladungen zu deklarieren, sollten wir den Restparameter ... args aus der Funktion fn als Typparameter verwenden, der das Array erweitert, und ihn dann für den Parameter ... args wiederverwenden, den die Aufruffunktion übergibt:

 function call<TS extends any[], R>(fn: (...args: TS) => R, ...args: TS): R { return fn(...args); } 

Wenn wir die Aufruffunktion aufrufen, versucht TypeScript, eine Liste von Parametern aus dem, was wir an fn übergeben, zu extrahieren und in ein Tupel umzuwandeln:

 function foo(x: number, y: string): string { return (x + y).toLowerCase(); } // The `TS` type parameter is inferred as `[number, string]` call(foo, 100, "hello"); 

Wenn TypeScript TS als [Nummer, Zeichenfolge] definiert und wir die Wiederverwendung von TS für den Restparameter der Aufruffunktion beenden, sieht die Funktionsinstanz folgendermaßen aus:

 function call(fn: (...args: [number, string]) => string, ...args: [number, string]): string 

Und in TypeScript 3.0 wird der Parameter bei Verwendung eines Tupels in Ruhe auf den Rest der Parameterliste minimiert! Die obige Instanz besteht aus einfachen Parametern ohne Tupel:

 function call(fn: (arg1: number, arg2: string) => string, arg1: number, arg2: string): string 

Zusätzlich zum Abfangen von Typkonvertierungsfehlern beim Übergeben ungültiger Argumente:

 function call<TS extends any[], R>(fn: (...args: TS) => R, ...args: TS): R { return fn(...args); } call((x: number, y: string) => y, "hello", "world"); // ~~~~~~~ // Error! `string` isn't assignable to `number`! 

... und Typdefinition aus anderen Argumenten:

 call((x, y) => { /* .... */ }, "hello", 100); // ^ ^ // `x` and `y` have their types inferred as `string` and `number` respectively. 

... wir können auch die Tupeltypen sehen, die diese Funktionen von außen definieren:

 function tuple<TS extends any[]>(...xs: TS): TS { return xs; } let x = tuple(1, 2, "hello"); // has type `[number, number, string]` 

Aber achten Sie auf eine Einschränkung. Um all diese Arbeit zu erledigen, mussten wir die Fähigkeiten von Tupeln erweitern ...

Neue Tupeltypfunktionen


Um die Parameterliste als Tupel zu modellieren (wie wir gerade besprochen haben), mussten wir die Tupeltypen ein wenig überdenken. Vor der Veröffentlichung von TypeScript 3.0 war die Reihenfolge und Länge des Parametersatzes das Beste, was mit Tupeln modelliert werden konnte.

Parameterlisten sind jedoch nicht nur geordnete Typlisten. Beispielsweise können die Parameter am Ende optional sein:

 // Both `y` and `z` are optional here. function foo(x: boolean, y = 100, z?: string) { // ... } foo(true); foo(true, undefined, "hello"); foo(true, 200); 

Der letzte Parameter kann ein Ruheparameter sein.

 // `rest` accepts any number of strings - even none! function foo(...rest: string[]) { // ... } foo(); foo("hello"); foo("hello", "world"); 

Und schließlich gibt es eine ziemlich interessante Eigenschaft von Parameterlisten - sie können leer sein:

 // Accepts no parameters. function foo() { // ... } foo(); 

Damit die Tupel den Parameterlisten entsprechen, mussten wir daher jedes dieser Szenarien simulieren.

Erstens kann es jetzt am Ende des Tupels optionale Elemente geben:

 /** * 2D, or potentially 3D, coordinate. */ type Coordinate = [number, number, number?]; 

Der Koordinatentyp erstellt ein Tupel mit einer optionalen Eigenschaft namens 2 - ein Element mit Index 2 ist möglicherweise nicht definiert! Interessanterweise ist die Längeneigenschaft des Coodinate-Tupels vom Typ 2 |, da Tupel für ihre Längeneigenschaft einen numerischen Literaltyp verwenden 3.

Zweitens kann das Restelement jetzt am Ende des Tupels vorhanden sein.

 type OneNumberAndSomeStrings = [number, ...string[]]; 

Dank der restlichen Elemente zeigen Tupel ein sehr interessantes Verhalten „unbegrenzt vom Ende“. Für das obige Beispiel vom Typ OneNumberAndSomeStrings muss der Typ seiner ersten Eigenschaft number sein, und eine oder mehrere Eigenschaften vom Typ string sind zulässig. Wenn Sie diesen Tupeltyp mit einer beliebigen Nummer nummerieren, wird die Typzeichenfolge | zurückgegeben Nummer, weil der Indexwert unbekannt ist. In ähnlicher Weise ist der Wert der Eigenschaft length einfach number, da die Länge des Tupels unbekannt ist.

Es ist zu beachten, dass in Abwesenheit anderer Elemente das Restelement im Tupel mit sich selbst identisch ist:

 type Foo = [...number[]]; // Equivalent to `number[]`. 

Endlich können Tupel jetzt leer sein! Obwohl dies bei Verwendung außerhalb von Parameterlisten nicht sehr nützlich ist, kann ein leerer Tupeltyp wie folgt definiert werden: []:

 type EmptyTuple = []; 

Wie zu erwarten ist, hat ein leeres Tupel die Länge-Eigenschaft 0, und die Indizierung mit Zahl gibt den Typ nie zurück.

Verbesserte Fehlerdiagnose und Benutzerumgebung


Im Laufe der Zeit erhalten wir immer mehr Anfragen von Mitgliedern unserer Community bezüglich der Verbesserung von Fehlermeldungen. Obwohl diese Arbeit noch lange nicht abgeschlossen ist, haben wir von Ihnen gehört und eine Reihe von Verbesserungen an der TypeScript 3.0-Version vorgenommen.

Zugehörige Fehlerbereiche


Zum Teil besteht das Ziel einer guten Fehlermeldung darin, dem Benutzer anzuzeigen, wie sie korrigiert werden soll, oder zunächst klar zu machen, warum diese Meldung angezeigt wird. In den meisten Fällen enthält es viele Informationen oder gibt mehrere Gründe für sein Auftreten an. Aus einer Analyse dieser Gründe können wir schließen, dass Fehler aus verschiedenen Teilen des Codes resultieren.

Zugehörige Fehlerbereiche sind eine neue Möglichkeit, diese Informationen Benutzern bereitzustellen. In TypeScript 3.0 können Fehlermeldungen an anderer Stelle im Code Meldungen generieren, damit Benutzer die Ursache und Wirkung des Fehlers herausfinden können.



In gewissem Sinne können verwandte Fehlermeldungen dem Benutzer nicht nur eine Erklärung geben, sondern auch den Pfad zu dem Ort angeben, an dem alles schief gelaufen ist.



Diese Intervalle werden auch im Terminalmodus angezeigt, wenn Sie den Befehl tsc mit aktiviertem --pretty-Modus ausführen. Wir arbeiten jedoch noch an der Verbesserung der Benutzeroberfläche und berücksichtigen Ihr Feedback!

Verbesserte Diagnose und Fehlerbehandlung


Bei der Vorbereitung der Veröffentlichung von TypeScript 2.9 haben wir begonnen, Fehlermeldungen mehr Aufmerksamkeit zu schenken , und in Version 3.0 haben wir wirklich versucht, die Hauptaufgaben zu lösen, die es uns ermöglichen würden, eine intelligente, klare und genaue Fehlerdiagnose durchzuführen. Dies umfasst insbesondere die Auswahl geeigneter Typen bei Inkonsistenzen bei den Zuordnungstypen und den direkten Übergang zur Fehlerquelle für bestimmte Nachrichtentypen.

Wir glauben, dass unsere Bemühungen gerechtfertigt waren, und als Ergebnis erhalten Sie kürzere und klarere Fehlermeldungen.





Typ unbekannt


Der Typ any ist ein beliebiger Typ in TypeScript, der für alles geeignet ist. Da es die Typen aller möglichen Werte abdeckt, werden wir nicht gezwungen, Überprüfungen durchzuführen, bevor wir versuchen, ihre Eigenschaften aufzurufen, zu konstruieren oder darauf zuzugreifen. Außerdem können Sie Variablen, die Werte eines anderen Typs erwarten, Werte vom Typ any zuweisen.

Diese Funktion ist im Allgemeinen nützlich, kann jedoch keine ausreichende Genauigkeit bieten.

 let foo: any = 10; // All of these will throw errors, but TypeScript // won't complain since `foo` has the type `any`. foo.x.prop; foo.y.prop; foo.z.prop; foo(); new foo(); upperCase(foo); foo `hello world!`; function upperCase(x: string) { return x.toUpperCase(); } 

Manchmal möchten Sie in TypeScript einen Typ beschreiben, der für nichts geeignet ist. Dies ist nützlich für eine API, die signalisieren möchte: "Es kann ein beliebiger Wert sein, daher müssen Sie vor der Verwendung einige Überprüfungen durchführen." Und Benutzer sind aus Sicherheitsgründen gezwungen, Rückgabewerte zu analysieren.

TypeScript 3.0 führt einen neuen Typ namens unknown ein, der genau das tut. Wie bei jedem Typ wird dem unbekannten Typ ein beliebiger Wert zugewiesen. Im Gegensatz zu jedem anderen Typ kann der unbekannte Typ jedoch ohne Typanweisung fast keinem anderen Typ zugewiesen werden.Sie können weder auf Objekte unbekannten Typs zugreifen noch sie aufrufen oder konstruieren.

Wenn Sie im obigen Beispiel unbekannt durch eines ersetzen, führt alle Fälle der Verwendung des foo-Objekts zu einem Fehler:

 let foo: unknown = 10; // Since `foo` has type `unknown`, TypeScript // errors on each of these locations. foo.x.prop; foo.y.prop; foo.z.prop; foo(); new foo(); upperCase(foo); foo `hello world!`; function upperCase(x: string) { return x.toUpperCase(); } 

Stattdessen müssen wir entweder eine Validierung durchführen oder eine Typzusicherung verwenden und das Typüberprüfungssystem davon überzeugen, dass wir besser wissen, was zu tun ist.

 let foo: unknown = 10; function hasXYZ(obj: any): obj is { x: any, y: any, z: any } { return !!obj && typeof obj === "object" && "x" in obj && "y" in obj && "z" in obj } // Using a user-defined type guard... if (hasXYZ(foo)) { // ...we're allowed to access certain properties again. foo.x.prop; foo.y.prop; foo.z.prop; } // We can also just convince TypeScript we know what we're doing // by using a type assertion. upperCase(foo as string); function upperCase(x: string) { return x.toUpperCase(); } 

Hinweis: Wenn Sie einen Typ wie {} | verwenden, um ein ähnliches Verhalten zu erzielen null | undefiniert verhält sich der unbekannte Typ in Konstruktionen wie bedingten Typen normalerweise wünschenswerter, da sich bedingte Typen auf Vereinigungstypen erstrecken:

 type Arrayify<T> = T extends any ? Array<T> : never; type A = Arrayify<{} | null | undefined>; // null[] | undefined[] | {}[] type B = Arrayify<unknown>; // unknown[] 

Unterstützung für defaultProps in JSX


: .d.ts React , , .

- TypeScript/JavaScript , , . , . , .

 function loudlyGreet(name = "world") { // Thanks to the default initializer, `name` will always have type `string` internally. // We don't have to check for `undefined` here. console.log("HELLO", name.toUpperCase()); } // Externally, `name` is optional, and we can potentially pass `undefined` or omit it entirely. loudlyGreet(); loudlyGreet(undefined); 

React (props). React , defaultProps, props.

 // Some non-TypeScript JSX file import * as React from "react"; import * as ReactDOM from "react-dom"; export class Greet extends React.Component { render() { const { name } = this.props; return <div>Hello ${name.toUpperCase()}!</div>; } static defaultProps = { name: "world", }; } // Notice no `name` attribute was specified! // vvvvvvvvv const result = ReactDOM.renderToString(<Greet />); console.log(result); 

, <Greet /> name. Greet, name «world», : Hello world!.

, TypeScript , defaultProps - JSX. render:

 export interface Props { name?: string } export class Greet extends React.Component<Props> { render() { const { name } = this.props; // Notice the `!` ------v return <div>Hello ${name!.toUpperCase()}!</div>; } static defaultProps = { name: "world"} } 

, .

TypeScript 3.0 JSX, LibraryManagedAttributes. , , TypeScript, JSX. , , React defaultProps , , propTypes.

 export interface Props { name: string } export class Greet extends React.Component<Props> { render() { const { name } = this.props; return <div>Hello ${name.toUpperCase()}!</div>; } static defaultProps = { name: "world"} } // Type-checks! No type assertions needed! let el = <Greet /> 

, . defaultProps, Partial , - (stateless function components, SFC), defaultProps Partial , . defaultProps (. ) SFC ES2015:

 function Greet({ name = "world" }: Props) { return <div>Hello ${name.toUpperCase()}!</div>; } 

, . TypeScript, .d.ts DefinitelyTyped , , @types/react . DefinitelyTyped, .

/// <reference lib="..." />


, , , (polyfills) — , API , ( .d.ts), API. , TypeScript lib.d.ts , --lib --target. , core-js lib.es2015.d.ts.

TypeScript 3.0 , API, , : /// <reference lib="..." />.

, Promise ES2015

 /// <reference lib="es2015.promise" /> export {}; 

, TypeScript 3.0 , lib.es2015.promise.d.ts, , Promise .


, , TypeScript , . TypeScript JavaScript , Visual Studio, Visual Studio Code TypeScript. , , , Go to Definition (« ») . TypeScript 3.0 .


, , .

 import * as dependency from "./dependency"; // look at all this repetition! dependency.foo(); dependency.bar(); dependency.baz(); 

, , , , .

 import { foo, bar, baz } from "./dependency"; // way lower in the file... foo(); bar(); baz(); 

, , . TypeScript 3.0 , .




TypeScript , JSX:

  • JSX;
  • JSX.




TypeScript — , .


, API .

, TypeScript 3 , . , API .

unknown —


unknown — , , , .

API


  • LanguageService#getSourceFile , . . #24540 .
  • TypeChecker#getSymbolDisplayBuilder . . #25331 . emitter ( ) node builder.
  • escapeIdentifier unescapeIdentifier . API , . , , . escapeLeadingUnderscores unescapeLeadingUnderscores, , ( «» __String string ).
  • TypeChecker#getSuggestionForNonexistentProperty, TypeChecker#getSuggestionForNonexistentSymbol TypeChecker#getSuggestionForNonexistentModule , API. . #25520 .

Perspektiven


TypeScript . , , , DefinitelyTyped , . , .

, TypeScript ( , ). , , JavaScript. , TypeScript, .

, , , , , Twitter . .

, TypeScript, ! . , , TypeScript , .

!
TypeScript

Source: https://habr.com/ru/post/de420761/


All Articles