We hebben de belangrijkste kenmerken van het TypeScript Typesysteem al besproken toen we het over Waarom TypeScript? hadden. Hieronder volgen enkele belangrijke conclusies uit die bespreking die geen verdere uitleg behoeven:

  • Het typesysteem in TypeScript is zo ontworpen dat het optioneel is, zodat uw JavaScript TypeScript is.

  • TypeScript blokkeert JavaScript niet in aanwezigheid van Type Errors, zodat u uw JS geleidelijk kunt bijwerken naar TS.

Nu beginnen we met de syntaxis van het TypeScript-type-systeem. Op deze manier kun je direct beginnen met het gebruik van deze annotaties in je code en het voordeel zien. Dit zal je voorbereiden op een diepere duik later.

Zoals eerder vermeld worden Types geannoteerd met behulp van :TypeAnnotation syntax. Alles wat beschikbaar is in de type declaratie ruimte kan worden gebruikt als een Type annotatie.

Het volgende voorbeeld demonstreert type annotaties voor variabelen, functie parameters en functie return waarden:

var num: number = 123;
function identity(num: number): number {
return num;
}

Primitieve Types

De JavaScript primitieve Types zijn goed vertegenwoordigd in het TypeScript type systeem. Dit betekent string, number, boolean zoals hieronder gedemonstreerd:

var num: number;
var str: string;
var bool: boolean;
num = 123;
num = 123.456;
num = '123'; // Error
str = '123';
str = 123; // Error
bool = true;
bool = false;
bool = 'false'; // Error

Arrays

TypeScript biedt een speciale typesyntaxis voor arrays om het eenvoudiger te maken om je code te annoteren en te documenteren. De syntaxis bestaat uit het postfixeren van op een geldige type annotatie (b.v. :boolean). Hiermee kunt u veilig elke array manipulatie doen die u normaal zou doen en wordt u beschermd tegen fouten zoals het toewijzen van een lid van het verkeerde type. Dit wordt hieronder gedemonstreerd:

var boolArray: boolean;
boolArray = ;
console.log(boolArray); // true
console.log(boolArray.length); // 2
boolArray = true;
boolArray = ;
boolArray = 'false'; // Error!
boolArray = 'false'; // Error!
boolArray = ; // Error!

Interfaces

Interfaces zijn de belangrijkste manier in TypeScript om meerdere type-annotaties samen te voegen tot een enkele annotatie met een naam. Neem het volgende voorbeeld:

interface Name {
first: string;
second: string;
}
var name: Name;
name = {
first: 'John',
second: 'Doe'
};
name = { // Error : `second` is missing
first: 'John'
};
name = { // Error : `second` is the wrong type
first: 'John',
second: 1337
};

Hier hebben we de annotaties first: string + second: string samengesteld tot een nieuwe annotatie Name die de type-controles afdwingt op individuele leden. Interfaces hebben veel kracht in TypeScript en we zullen een hele sectie wijden aan hoe je dat in je voordeel kunt gebruiken.

Inline Type Annotatie

In plaats van een nieuwe interface te maken kun je alles wat je wilt inline annoteren met :{ /*Structure*/ }. Het vorige voorbeeld gaf weer een inline type:

var name: {
first: string;
second: string;
};
name = {
first: 'John',
second: 'Doe'
};
name = { // Error : `second` is missing
first: 'John'
};
name = { // Error : `second` is the wrong type
first: 'John',
second: 1337
};

Inline types zijn geweldig om snel een eenmalige type annotatie voor iets te maken. Het bespaart je de moeite om een (mogelijk slechte) typenaam te bedenken. Als je echter dezelfde type annotatie meerdere malen inline gebruikt, is het een goed idee om te overwegen om het te refactoren in een interface (of een type alias die later in deze sectie wordt behandeld).

Speciale Types

Naast de primitieve types die al behandeld zijn, zijn er nog een paar types die een speciale betekenis hebben in TypeScript. Dit zijn any, null, undefined, void.

elke

Het any type neemt een speciale plaats in het TypeScript typesysteem in. Het geeft je een ontsnappingsluik uit het typesysteem om de compiler te vertellen dat hij kan oprotten. any is compatibel met alle types in het typesysteem. Dit betekent dat alles er aan toegewezen kan worden en dat alles er aan toegewezen kan worden. Dit wordt gedemonstreerd in het onderstaande voorbeeld:

var power: any;
// Takes any and all types
power = '123';
power = 123;
// Is compatible with all types
var num: number;
power = num;
num = power;

Als u JavaScript code overzet naar TypeScript, zult u in het begin goede vrienden worden met any. Neem deze vriendschap echter niet te serieus, want het betekent dat het aan u is om de typeveiligheid te garanderen. U vertelt de compiler in feite om geen zinvolle statische analyse te doen.

null en undefined

Hoe ze door het typesysteem worden behandeld, hangt af van de strictNullChecks compiler vlag (we behandelen deze vlag later). In strictNullCheck:false worden de null en undefined JavaScript-literalen door het systeem hetzelfde behandeld als iets van het type any. Deze lettertekens kunnen aan elk ander type worden toegewezen. Dit wordt gedemonstreerd in het onderstaande voorbeeld:

var num: number;
var str: string;
// These literals can be assigned to anything
num = null;
str = undefined;

:void

Gebruik :void om aan te geven dat een functie geen terugkeertype heeft:

function log(message): void {
console.log(message);
}

Generics

Veel algoritmen en gegevensstructuren in de informatica zijn niet afhankelijk van het werkelijke type van het object. Toch wil je een beperking afdwingen tussen verschillende variabelen. Een eenvoudig speelgoedvoorbeeld is een functie die een lijst van items neemt en een omgekeerde lijst van items teruggeeft. De beperking hier is tussen wat wordt doorgegeven aan de functie en wat wordt geretourneerd door de functie:

function reverse<T>(items: T): T {
var toreturn = ;
for (let i = items.length - 1; i >= 0; i--) {
toreturn.push(items);
}
return toreturn;
}
var sample = ;
var reversed = reverse(sample);
console.log(reversed); // 3,2,1
// Safety!
reversed = '1'; // Error!
reversed = ; // Error!
reversed = 1; // Okay
reversed = ; // Okay

Hier zegt u in feite dat de functie reverse een array (items: T) neemt van een bepaald type T (let op de type-parameter in reverse<T>) en een array retourneert van het type T (let op : T). Omdat de functie reverse items retourneert van hetzelfde type als het inneemt, weet TypeScript dat de variabele reversed ook van het type number is en zal het Type veiligheid geven. Op dezelfde manier als je een array van string doorgeeft aan de omgekeerde functie, is het geretourneerde resultaat ook een array van string en krijg je een vergelijkbare type-veiligheid zoals hieronder te zien is:

var strArr = ;
var reversedStrs = reverse(strArr);
reversedStrs = ; // Error!

In feite hebben JavaScript arrays al een .reverse functie en TypeScript gebruikt inderdaad generics om de structuur te definiëren:

interface Array<T> {
reverse(): T;
// ...
}

Dit betekent dat u typeveiligheid krijgt wanneer u .reverse aanroept op een willekeurige array, zoals hieronder te zien is:

var numArr = ;
var reversedNums = numArr.reverse();
reversedNums = ; // Error!

We zullen later meer bespreken over de Array<T> interface wanneer we lib.d.ts presenteren in de sectie Omgevingsverklaringen.

Union Type

Natuurlijk wil je in JavaScript toestaan dat een eigenschap een van meerdere types is, b.v. een string of een number. Dit is waar het union type (aangeduid met | in een type-annotatie, bijv. string|number) van pas komt. Een veelvoorkomend gebruik is een functie die een enkel object of een array van objecten kan nemen, bijvoorbeeld:

function formatCommandline(command: string|string) {
var line = '';
if (typeof command === 'string') {
line = command.trim();
} else {
line = command.join(' ').trim();
}
// Do stuff with line: string
}

Intersection Type

extend is een veelvoorkomend patroon in JavaScript, waarbij je twee objecten neemt en een nieuw object maakt dat de eigenschappen van beide objecten heeft. Met een Intersection Type kun je dit patroon op een veilige manier gebruiken, zoals hieronder wordt gedemonstreerd:

function extend<T, U>(first: T, second: U): T & U {
return { ...first, ...second };
}
const x = extend({ a: "hello" }, { b: 42 });
// x now has both `a` and `b`
const a = x.a;
const b = x.b;

Tuple Type

JavaScript heeft geen eerste klas tuple ondersteuning. Mensen gebruiken over het algemeen gewoon een array als een tuple. Dit is precies wat het TypeScript typesysteem ondersteunt. Tuples kunnen geannoteerd worden met : enz. Een tuple kan een willekeurig aantal leden hebben. Tuples worden gedemonstreerd in het onderstaande voorbeeld:

var nameNumber: ;
// Okay
nameNumber = ;
// Error!
nameNumber = ;

Combineer dit met de destructureringsondersteuning in TypeScript, dan voelen tuples redelijk eerste klas aan, ondanks dat ze onderliggend arrays zijn:

var nameNumber: ;
nameNumber = ;
var = nameNumber;

Type Alias

TypeScript biedt een handige syntaxis voor het geven van namen aan type-annotaties die je op meer dan één plaats wilt gebruiken. De aliassen worden gemaakt met behulp van de type SomeName = someValidTypeAnnotation syntaxis. Een voorbeeld staat hieronder:

type StrOrNum = string|number;
// Usage: just like any other notation
var sample: StrOrNum;
sample = 123;
sample = '123';
// Just checking
sample = true; // Error!

In tegenstelling tot een interface kun je een type alias geven aan letterlijk elke type annotatie (handig voor dingen als union en intersection types). Hier zijn nog een paar voorbeelden om u vertrouwd te maken met de syntaxis:

type Text = string | { text: string };
type Coordinates = ;
type Callback = (data: string) => void;

TIP: Als u hiërarchieën van type-annotaties moet hebben, gebruikt u een interface. Ze kunnen worden gebruikt met implements en extends

TIP: Gebruik een type-alias voor eenvoudigere objectstructuren (zoals Coordinates) om ze een semantische naam te geven. Ook wanneer u semantische namen wilt geven aan Union- of Intersection-types, is een Type-alias de aangewezen weg.

Samenvatting

Nu u het grootste deel van uw JavaScript-code kunt annoteren, kunnen we dieper ingaan op de details van alle mogelijkheden die TypeScript met zijn Type System biedt.

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.