Vi tog upp de viktigaste funktionerna i TypeScript Type System när vi diskuterade Varför TypeScript?. Nedan följer några viktiga behållningar från den diskussionen som inte behöver förklaras ytterligare:

  • Typsystemet i TypeScript är utformat för att vara valfritt så att ditt JavaScript är TypeScript.

  • TypeScript blockerar inte JavaScript emit i närvaro av typfel, vilket gör att du successivt kan uppdatera ditt JS till TS.

Nu börjar vi med syntaxen för TypeScript-typssystemet. På så sätt kan du börja använda dessa annotationer i din kod omedelbart och se fördelarna. Detta kommer att förbereda dig för en djupare dykning senare.

Som tidigare nämnts annoteras typer med hjälp av :TypeAnnotation syntax. Allt som är tillgängligt i typdeklarationsutrymmet kan användas som en typannotation.

Följande exempel visar typannotationer för variabler, funktionsparametrar och funktionsreturvärden:

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

Primitiva typer

De primitiva typerna i JavaScript är väl representerade i TypeScript-typsystemet. Detta innebär string, number, boolean som demonstreras nedan:

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 tillhandahåller dedikerad typsyntax för arrays för att göra det lättare för dig att kommentera och dokumentera din kod. Syntaxen går i princip ut på att postfixera till vilken giltig typannotation som helst (t.ex. :boolean). Den gör det möjligt för dig att på ett säkert sätt göra all array-manipulation som du normalt skulle göra och skyddar dig från fel som till exempel att tilldela en medlem av fel typ. Detta demonstreras nedan:

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

Gränssnitt

Gränssnitt är det centrala sättet i TypeScript att komponera flera typannotationer till en enda namngiven annotation. Tänk på följande exempel:

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
};

Här har vi komponerat annotationerna first: string + second: string till en ny annotation Name som verkställer typkontrollerna på enskilda medlemmar. Gränssnitt har mycket kraft i TypeScript och vi kommer att ägna ett helt avsnitt åt hur du kan använda det till din fördel.

Inline Type Annotation

Istället för att skapa en ny interface kan du annotera vad du vill inline med :{ /*Structure*/ }. Föregående exempel presenterades återigen med en inline-typ:

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-typer är utmärkta för att snabbt tillhandahålla en engångsannotation för något. Det besparar dig besväret med att komma på ett (potentiellt dåligt) typnamn. Men om du upptäcker att du sätter in samma typannotation inline flera gånger är det en bra idé att överväga att refaktorisera den till ett gränssnitt (eller en type alias som behandlas senare i det här avsnittet).

Speciella typer

Bortom de primitiva typerna som har behandlats finns det några typer som har en speciell betydelse i TypeScript. Dessa är any, null, undefined, void.

any

Typen any har en speciell plats i TypeScript-typssystemet. Den ger dig en flyktlucka från typsystemet för att tala om för kompilatorn att dra åt helvete. any är kompatibel med alla typer i typsystemet. Det betyder att vad som helst kan tilldelas den och att den kan tilldelas vad som helst. Detta demonstreras i exemplet nedan:

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

Om du porterar JavaScript-kod till TypeScript kommer du att vara nära vän med any i början. Ta dock inte denna vänskap på alltför stort allvar eftersom den innebär att det är upp till dig att garantera typsäkerheten. Du säger i princip till kompilatorn att inte göra någon meningsfull statisk analys.

null och undefined

Hur de behandlas av typsystemet beror på kompilatorflaggan strictNullChecks (vi tar upp denna flagga senare). När de står i strictNullCheck:false behandlas null och undefined JavaScript-litteralerna i praktiken av typsystemet på samma sätt som något av typen any. Dessa literaler kan tilldelas vilken annan typ som helst. Detta visas i nedanstående exempel:

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

:void

Använd :void för att ange att en funktion inte har någon returtyp:

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

Generics

Många algoritmer och datastrukturer inom datavetenskapen beror inte på objektets faktiska typ. Men du vill ändå upprätthålla en begränsning mellan olika variabler. Ett enkelt leksaksexempel är en funktion som tar en lista med objekt och returnerar en omvänd lista med objekt. Begränsningen här är mellan det som skickas in till funktionen och det som returneras av funktionen:

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

Här säger du i princip att funktionen reverse tar en array (items: T) av en viss typ T (lägg märke till typparametern i reverse<T>) och returnerar en array av typen T (lägg märke till : T). Eftersom funktionen reverse returnerar objekt av samma typ som den tar, vet TypeScript att variabeln reversed också är av typen number och ger dig typ-säkerhet. På samma sätt om du skickar in en array av string till den omvända funktionen är det returnerade resultatet också en array av string och du får liknande typsäkerhet som visas nedan:

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

I själva verket har JavaScript-matriser redan en .reverse-funktion och TypeScript använder faktiskt generics för att definiera dess struktur:

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

Detta innebär att du får typsäkerhet när du anropar .reverse på en array som visas nedan:

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

Vi kommer att diskutera mer om gränssnittet Array<T> senare när vi presenterar lib.d.ts i avsnittet Ambient Declarations.

Union Type

Ganska ofta i JavaScript vill man tillåta att en egenskap kan vara en av flera typer, t.ex. en string eller en number. Det är här som unionstypen (betecknad med | i en typannotation, t.ex. string|number) är användbar. Ett vanligt användningsfall är en funktion som kan ta ett enda objekt eller en array av objektet t.ex.:

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

Intersektionstyp

extend är ett mycket vanligt mönster i JavaScript där man tar två objekt och skapar ett nytt som har egenskaperna hos båda dessa objekt. Med en Intersection Type kan du använda det här mönstret på ett säkert sätt, vilket demonstreras nedan:

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;

Tupeltyp

JavaScript har inte stöd för första klassens tupel. Folk använder i allmänhet bara en array som en tupel. Detta är precis vad TypeScript-typ systemet stöder. Tupler kan kommenteras med hjälp av : osv. En tupel kan ha valfritt antal medlemmar. Tuples demonstreras i nedanstående exempel:

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

Kombinera detta med destruktionsstödet i TypeScript, tuples känns ganska förstklassiga trots att de är matriser under:

var nameNumber: ;
nameNumber = ;
var = nameNumber;

Type Alias

TypeScript tillhandahåller en praktisk syntax för att ge namn till typannotationer som du vill använda på mer än ett ställe. Aliaserna skapas med hjälp av type SomeName = someValidTypeAnnotation-syntaxen. Ett exempel visas nedan:

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

Till skillnad från en interface kan du ge ett typalias till bokstavligen vilken typannotation som helst (användbart för saker som union- och intersektionstyper). Här är ytterligare några exempel för att göra dig bekant med syntaxen:

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

TIP: Om du behöver ha hierarkier av typannotationer använder du en interface. De kan användas med implements och extends

TIP: Använd ett typalias för enklare objektstrukturer (som Coordinates) bara för att ge dem ett semantiskt namn. Även när du vill ge semantiska namn till union- eller intersektionstyper är ett typalias rätt väg att gå.

Sammanfattning

Nu när du kan börja annotera det mesta av din JavaScript-kod kan vi hoppa in i de små detaljerna om all den kraft som finns tillgänglig i TypeScript’s Type System.

Lämna ett svar

Din e-postadress kommer inte publiceras.