TypeScript 3.0 – die Neuerungen

TypeScript 3.0 – das sind die Neuerungen

Avatar von Christopher Stock

Am 30. Juli 2018 wurde TypeScript 3.0 veröffentlicht. Die quelloffene Transpiler-Sprache aus dem Hause Microsoft feiert damit ihr knapp sechsjähriges Bestehen und da ich selbst ein großer Fan von TypeScript bin, möchte ich Euch in diesem Artikel die wichtigsten Neuerungen dieser Version kurz vorstellen.

Projektreferenzen

Unter TypeScript 3.0 können erstmalig externe TypeScript-Projekte über deren eigenständige tsconfig.json-Datei referenziert und somit als Abhängigkeit definiert werden. Über die neue Angabe references in der tsconfig.json kann der Dateipfad externer TypeScript-Projekte angegeben und somit beim Kompilieren des Projektes berücksichtigt werden.

Die folgende Compiler-Config unter frontend/tsconfig.json referenziert die beiden Projekte backend und e2e-test über deren entsprechende tsconfig.json-Files:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"compilerOptions": {
// all compiler options – as ever
},
"references": [
{
"path": "../backend"
},
{
"path": "../e2e-test"
},
],
}
{ "compilerOptions": { // all compiler options – as ever }, "references": [ { "path": "../backend" }, { "path": "../e2e-test" }, ], }
{
    "compilerOptions": {

        // all compiler options – as ever

    },

    "references": [
        {
            "path": "../backend"
        },
        {
            "path": "../e2e-test"
        },
    ],
}

Beim Kompilieren eines Projektes werden die eigenen Sourcefiles neu kompiliert. Die Quelldateien der referenzierten Projekte werden nur dann kompiliert, wenn dies erforderlich ist, ansonsten werden nur deren TypeScript Declaration Files (.d.ts) verwendet. Hierdurch werden die Kompilierzeit sowei die IDE-Speichernutzung eines Projektes deutlich optimiert und zudem noch eine logische Trennung des Projektcodes gefördert.

Sinnvoll ist das beispielsweise beim Erstellen eines Microservices und der daraus resultierenden Trennung der TypeScript-Quellcodes in mehrere Projekte wie frontend, backend und test.

Erweiterte Funktionen für Tupel

Tupel sind unter TypeScript bereits seit der Version 1.3 verfügbar. Mit diesem Datentyp kann ein Array definiert werden, dessen Elemente nicht aus einem einzelnen, sondern aus unterschiedlichen Datentypen bestehen können. Der folgende Codeschnipsel demonstriert den Einsatz eines Tupels:

Goodies von Mayflower

 

Das klingt nach einem Thema, dass Dich in Deinem Alltag bei euch beschäftigt? Das Dich mit vielen Fragen zurück lässt?

Keine Sorge – Hilfe ist nah! Melde Dich unverbindlich bei uns und wir schauen uns gemeinsam an, ob und wie wir Dich unterstützen können.


Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let myFruitBowl: [ string, number ];
// compiles correctly
myFruitBowl = [ 'Apple', 4 ]; // OK
// compilation fails here
myFruitBowl = [ 4, 'Apple' ];
let myFruitBowl: [ string, number ]; // compiles correctly myFruitBowl = [ 'Apple', 4 ]; // OK // compilation fails here myFruitBowl = [ 4, 'Apple' ];
let myFruitBowl: [ string, number ];

// compiles correctly
myFruitBowl = [ 'Apple', 4 ]; // OK

// compilation fails here
myFruitBowl = [ 4, 'Apple' ];

Ab der Major-Version 3 bietet TypeScript nun ein paar ausgewählte neue Funktionalitäten für diesen Datentyp an:

Rest-Parameter für Tupel

Als Datentyp für Rest-Parameter war bisher lediglich ein Array zulässig. Der folgende Codeschnipsel demonstriert kurz und bündig den Einsatz eines Rest-Parameters:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function myFunction( ...args:number[] ) : void
{
console.log( 'Number of args: [' + args.length + ']' );
}
myFunction( 0, 1, 2, 3, 4 );
// output is: 'Number of args: [5]'
function myFunction( ...args:number[] ) : void { console.log( 'Number of args: [' + args.length + ']' ); } myFunction( 0, 1, 2, 3, 4 ); // output is: 'Number of args: [5]'
function myFunction( ...args:number[] ) : void
{
    console.log( 'Number of args: [' + args.length + ']' );
}

myFunction( 0, 1, 2, 3, 4 ); 

// output is: 'Number of args: [5]'

Nun ermöglicht TypeScript 3.0 auch den Einsatz des Tupel-Datentyps als Rest-Parameter für Funktionen. Die folgenden beiden Funktionen sind somit ab sofort äquivalent:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function myFunctionA( ...args: [ number, string, boolean ] ) : void
{
}
function myFunctionB( args_0: number, args_1: string, args_2: boolean ) : void
{
}
function myFunctionA( ...args: [ number, string, boolean ] ) : void { } function myFunctionB( args_0: number, args_1: string, args_2: boolean ) : void { }
function myFunctionA( ...args: [ number, string, boolean ] ) : void
{
}

function myFunctionB( args_0: number, args_1: string, args_2: boolean ) : void
{
}

Spread-Expressions für Tupel

Analog zur Unterstützung des Tupel-Datentyps als Rest-Parameter einer Funktion kann dieser Typ nun auch als Spread-Expression beim Aufrufen einer Funktion angegeben werden.

Die folgenden drei Aufrufe von myFunctionA sind daher äquivalent:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const args: [ number, string, boolean ] = [ 42, "hello", true ];
// all invocations are equivalent
myFunctionA( 42, "hello", true );
myFunctionA( args[ 0 ], args[ 1 ], args[ 2 ] );
myFunctionA( ...args );
const args: [ number, string, boolean ] = [ 42, "hello", true ]; // all invocations are equivalent myFunctionA( 42, "hello", true ); myFunctionA( args[ 0 ], args[ 1 ], args[ 2 ] ); myFunctionA( ...args );
const args: [ number, string, boolean ] = [ 42, "hello", true ];

// all invocations are equivalent
myFunctionA( 42, "hello", true );
myFunctionA( args[ 0 ], args[ 1 ], args[ 2 ] );
myFunctionA( ...args );

Optionale Tupel-Parameter

Ab TypeScript 3.0 können Parameter eines Tupels auch mittels der ?-Notation als optional gekennzeichnet werden. Somit quittiert der TypeScript-Compiler das Ausbleiben eines Parameters nicht mehr als Fehler:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let myTuple: [ number, string?, boolean? ];
myTuple = [42, "hello", true];
myTuple = [42, "hello"];
myTuple = [42];
let myTuple: [ number, string?, boolean? ]; myTuple = [42, "hello", true]; myTuple = [42, "hello"]; myTuple = [42];
let myTuple: [ number, string?, boolean? ];

myTuple = [42, "hello", true];
myTuple = [42, "hello"];
myTuple = [42];

Da ich ein Verfechter von sprechendem Code und dem Clustern zusammengehöriger Felder und Informationen in sprechende Klassen und Schnittstellen bin, kann ich von der Verwendung von Tupeln nur abraten. Trotzdem begegnet einem in der Praxis und in bestimmten Anwendungsfällen dieses Konstrukt hin und wieder, weswegen es nicht schaden kann, die Einsatzmöglichkeiten und Vorkommnisse dieses Features zu kennen.

Neuer Datentyp “unknown“

Neben den wichtigsten grundlegenden Datentypen boolean, number, string, undefined, any und null bietet TypeScript ab Version 3.0 den neuen Datentyp unknown an. Dieser stellt das typsichere Äquivalent zu dem nicht-typsicheren Datentyp any dar. Einer Variable vom Typ unknown können Werte aller beliebiger Datentypen zugewiesen werden, für den umgekehrten Vorgang bedarf es aber einer expliziten Typisierung.

Der folgende Code unter Einsatz des Datentyps any kompiliert korrekt:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let myAny :any = 42;
let myNumber :number = myAny;
let myAny :any = 42; let myNumber :number = myAny;
let myAny    :any    = 42;
let myNumber :number = myAny;

Der selbe Code unter Einsatz des Datentyps unknown wirft beim Kompilieren einen Fehler:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let myUnknown :unknown = 42;
let myNumber :number = myUnknown;
let myUnknown :unknown = 42; let myNumber :number = myUnknown;
let myUnknown :unknown = 42;
let myNumber  :number  = myUnknown;

Zum Fixen des Compilerproblems muss eine explizite Typisierung angegeben werden:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let myUnknown :unknown = 42;
let myNumber :number = myUnknown as number;
let myUnknown :unknown = 42; let myNumber :number = myUnknown as number;
let myUnknown :unknown = 42;
let myNumber  :number  = myUnknown as number;

Der Datentyp unknown bietet sich besonders für Portierungen von (untypisiertem) JavaScript-Code nach TypeScript an und bietet dabei einen höheren Pragmatismus.

Unterstützung für “defaultProps“ in JSX-Elementen

Der Einsatz des statischen Feldes defaultProps innerhalb von React-Komponenten wird nun auch im TypeScript-Code unterstützt.

Die folgende React-Komponente src/de/mayflower/tasklist/components/Greet.tsx kann verwendet werden, ohne dabei Properties in Form von Attributen zu übergeben. In diesem Falle werden die Properties aus dem statischen Feld defaultProps zugewiesen:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export interface Props
{
name: string;
}
export class Greet extends React.Component<Props>
{
static defaultProps = { name: "world"};
render() {
const { name } = this.props;
return <div>Hello ${name.toUpperCase()}!</div>;
}
}
// Type-checks! No type assertions needed!
let el = <Greet />
export interface Props { name: string; } export class Greet extends React.Component<Props> { static defaultProps = { name: "world"}; render() { const { name } = this.props; return <div>Hello ${name.toUpperCase()}!</div>; } } // Type-checks! No type assertions needed! let el = <Greet />
export interface Props
{
    name: string;
}

export class Greet extends React.Component<Props> 
{
    static defaultProps = { name: "world"};

    render() {
        const { name } = this.props;
        return <div>Hello ${name.toUpperCase()}!</div>;
    }
}

// Type-checks! No type assertions needed!
let el = <Greet />

Neue Referenzanweisung für built-in Libs

Mit der folgenden Angabe kann dem Compiler eine weitere TypeScript-Quelldatei an der angegebenen Stelle inkludiert werden. Auch kann durch diese Anweisung die explizite Reihenfolge der zu kompilierenden Dateien festgelegt werden.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/// <reference path="src/de/mayflower/util/MathUtil.ts" />
/// <reference path="src/de/mayflower/util/MathUtil.ts" />
/// <reference path="src/de/mayflower/util/MathUtil.ts" />

Nun kann über diese neue Referenzanweisung eine built-in Lib angegeben werden, sodass sie der Compiler beim Kompilieren berücksichtigt und die hierdurch zur Verfügung gestellten Funktionalitäten erkennt. Im folgenden Beispiel wird die String-Funktion padStart( size ) ermöglicht, die ohne die Angabe der neuen Referenzanweisung nicht gefunden würde.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/// <reference lib="es2017.string" />
console.log( 'Left padded foo: [' + ( 'foo'.padStart( 10 ) ) + ']' );
// Left padded foo: [ foo]
/// <reference lib="es2017.string" /> console.log( 'Left padded foo: [' + ( 'foo'.padStart( 10 ) ) + ']' ); // Left padded foo: [ foo]
/// <reference lib="es2017.string" />

console.log( 'Left padded foo: [' + ( 'foo'.padStart( 10 ) ) + ']' );

// Left padded foo: [       foo]

Diese Angabe ist äquivalent zur Verwendung der Compiler-Option

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
--lib es2017.string
--lib es2017.string
--lib es2017.string

Unter Verwendung von Webpack sind diese Referenzanweisungen allerdings obsolet, da hier mit dem Schlüsselwort import sowie mit lib-Angaben in der webpack.config.js gearbeitet werden sollte.

TypeScript 3.0

Unterm Strich sind die Änderungen der neuen Major-Version 3.0 überschaubar. Besonders löblich ist für mich die Tatsache, dass TypeScript 3.0 mit so gut wie gar keinen Breaking Changes daherkommt und einige neue Konzepte und Ideen bereithält.

Für fachliche Rückfragen und Anregungen stehe ich Euch wie immer gerne unter christopher.stock@mayflower.de zur Verfügung.

Goodies von Mayflower

Keine Sorge – Hilfe ist nah! Melde Dich unverbindlich bei uns und wir schauen uns gemeinsam an, ob und wie wir Dich unterstützen können.

Unsere Data-Webinar-Reihe

Avatar von Christopher Stock

Kommentare

6 Antworten zu „TypeScript 3.0 – das sind die Neuerungen“

  1. TypeScript 3.0 – das sind die Neuerungen https://t.co/887FkPMRd2 via @mayflowergmbh

  2. Was sind die Neuerungen in #typescript 3? Unser @jenetic1980 hat sich die Sache etwas genauer angesehen: https://t.co/EjTd017cdo

  3. Was die Neuerungen in #typescript 3 bedeuten lest ihr hier: https://t.co/EjTd01oN4W

  4. Interessiert ihr euch für die Neuerungen rund um #typescript 3? Unser @jenetic1980 hat sie sich angesehen und für e… https://t.co/z8An46gIqJ

  5. Wollt ihr wissen, was es mit den Neuerungen in #typescript 3 auf sich hat? @jenetic1980 hat sie sich genauer angese… https://t.co/fPMXm9qRde

  6. Ihr habt euch noch nicht mit #typescript 3 beschäftigt? Dann wird es aber Zeit: https://t.co/EjTd01oN4W

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Für das Handling unseres Newsletters nutzen wir den Dienst HubSpot. Mehr Informationen, insbesondere auch zu Deinem Widerrufsrecht, kannst Du jederzeit unserer Datenschutzerklärung entnehmen.