A TypeScript Type System főbb jellemzőit már ismertettük, amikor a Miért TypeScript? témát tárgyaltuk. Az alábbiakban bemutatunk néhány kulcsfontosságú megállapítást abból a beszélgetésből, amelyek nem szorulnak további magyarázatra:

  • A TypeScript típusrendszerét úgy terveztük, hogy opcionális legyen, hogy a JavaScripted TypeScript legyen.

  • A TypeScript nem blokkolja a JavaScript kibocsátását típushibák esetén, lehetővé téve, hogy fokozatosan frissítsd a JS-edet TS-re.

Most kezdjük a TypeScript típusrendszerének szintaxisával. Így azonnal elkezdheted használni ezeket az annotációkat a kódodban, és láthatod az előnyeit. Ez felkészít a későbbi mélyebb merülésre.

Mint már említettük, a típusokat a :TypeAnnotation szintaxis segítségével jegyzeteljük. Bármi, ami a típusdeklarációs térben elérhető, használható típusjelölésként.

A következő példa a változók, függvényparaméterek és függvényvisszatérési értékek típusjelöléseit mutatja be:

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

Primitív típusok

A JavaScript primitív típusai jól reprezentáltak a TypeScript típusrendszerében. Ez az alábbiakban bemutatott string, number, boolean típusokat jelenti:

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

Tömbök

A TypeScript külön típusszintaxist biztosít a tömbök számára, hogy megkönnyítse a kód megjegyzése és dokumentálása. A szintaxis alapvetően a utótagja bármely érvényes típusjelölésnek (pl. :boolean). Ez lehetővé teszi, hogy biztonságosan elvégezzen minden olyan tömbmanipulációt, amelyet általában elvégezne, és megvédi az olyan hibáktól, mint például egy rossz típusú tag hozzárendelése. Ezt az alábbiakban mutatjuk be:

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

A TypeScriptben az interfaces az alapvető módja annak, hogy több típus annotációt egyetlen megnevezett annotációvá állítsunk össze. Tekintsük a következő példát:

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

Itt a first: string + second: string annotációkat egy új Name annotációvá állítottuk össze, amely a típusellenőrzéseket az egyes tagokon érvényesíti. A TypeScriptben az interfészeknek rengeteg erejük van, és egy egész fejezetet szentelünk annak, hogyan használhatod ezt ki.

Inline Type Annotation

Ahelyett, hogy egy új interface-t hoznál létre, a :{ /*Structure*/ } segítségével inline annotálhatsz bármit, amit csak akarsz. Az előző példa ismét egy inline típussal bemutatott:

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

Az inline típusok kiválóan alkalmasak arra, hogy gyorsan megadjunk egy egyszeri típusmegjelölést valaminek. Megspórolja a (potenciálisan rossz) típusnév kitalálásának gondját. Ha azonban azon kapjuk magunkat, hogy ugyanazt a típusjelölést többször is inline adjuk meg, akkor jó ötlet megfontolni a refaktorálást egy interfésszé (vagy egy type alias később ebben a szakaszban tárgyalt

Speciális típusok

A már tárgyalt primitív típusokon túl van néhány olyan típus, amelynek különleges jelentése van a TypeScriptben. Ezek a any, null, undefined, void.

bármilyen

A any típus különleges helyet foglal el a TypeScript típusrendszerében. Ez egy menekülőnyílást ad a típusrendszerből, hogy megmondd a fordítónak, hogy húzzon el a fenébe. A any kompatibilis a típusrendszer minden típusával. Ez azt jelenti, hogy bármi hozzárendelhető, és bármihez hozzárendelhető. Ezt mutatja az alábbi példa:

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

Ha JavaScript kódot portolsz TypeScriptre, akkor az elején szoros barátságot fogsz kötni a any-vel. Ezt a barátságot azonban ne vedd túl komolyan, mivel ez azt jelenti, hogy a típusbiztonság biztosítása rajtad múlik. Alapvetően azt mondod a fordítónak, hogy ne végezzen értelmes statikus elemzést.

null és undefined

Az, hogy a típusrendszer hogyan kezeli őket, a strictNullChecks fordítói flagtől függ (ezzel a flaggel később foglalkozunk). Amikor strictNullCheck:false, a null és undefined JavaScript literálokat a típusrendszer gyakorlatilag ugyanúgy kezeli, mint valami any típusú dolgot. Ezek a literálok bármely más típushoz hozzárendelhetők. Ezt mutatja az alábbi példa:

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

:void

A :void használatával jelezhetjük, hogy egy függvénynek nincs visszatérési típusa:

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

Generika

A számítástechnikában sok algoritmus és adatszerkezet nem függ az objektum tényleges típusától. Ennek ellenére mégis korlátozást akarunk érvényesíteni a különböző változók között. Egy egyszerű játékpélda egy olyan függvény, amely egy elemlistát vesz, és egy fordított elemlistát ad vissza. A megkötés itt a függvénynek átadott és a függvény által visszaadott adatok között van:

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

Itt alapvetően azt mondjuk, hogy a reverse függvény egy T típusú tömböt (items: T) vesz (figyeljük meg a reverse<T> típusú paramétert) és egy T típusú tömböt ad vissza (figyeljük meg : T). Mivel a reverse függvény ugyanolyan típusú elemeket ad vissza, mint amilyen típusúakat felvesz, a TypeScript tudja, hogy a reversed változó is number típusú, és típusbiztonságot ad. Hasonlóképpen, ha egy string tömböt adunk át a fordított függvénynek, a visszaadott eredmény szintén egy string tömb lesz, és hasonló típusbiztonságot kapunk, mint az alábbiakban látható:

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

Tény, hogy a JavaScript tömböknek már van egy .reverse függvényük, és a TypeScript valóban használja a generikusokat a struktúra meghatározására:

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

Ez azt jelenti, hogy a .reverse hívásakor bármilyen tömbön típusbiztonságot kapunk, ahogy az alábbiakban látható:

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

A Array<T> interfészről később még többet fogunk beszélni, amikor a lib.d.ts-t bemutatjuk a Környezeti deklarációk fejezetben.

Union Type

A JavaScriptben elég gyakran szeretnénk lehetővé tenni, hogy egy tulajdonság többféle típusú legyen, például egy string vagy egy number. Itt jön jól az union típus (amelyet | jelöl egy típusmegjelölésben, pl. string|number). Gyakori felhasználási eset egy olyan függvény, amely egyetlen objektumot vagy az objektum tömbjét veheti pl.:

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

A metszet típus

extend egy nagyon gyakori minta a JavaScriptben, ahol veszünk két objektumot és létrehozunk egy újat, amely rendelkezik mindkét objektum tulajdonságaival. Az Intersection Type lehetővé teszi, hogy ezt a mintát biztonságos módon használjuk az alábbiakban bemutatott módon:

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

A JavaScript nem rendelkezik első osztályú tuple támogatással. Az emberek általában csak egy tömböt használnak tuple-ként. A TypeScript típusrendszere pontosan ezt támogatja. A tuplikat a : stb. használatával lehet megjegyzésekkel ellátni. Egy tuple tetszőleges számú taggal rendelkezhet. A tuple-okat az alábbi példában mutatjuk be:

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

Ezt kombinálva a TypeScript destructuring támogatásával, a tuple-ok meglehetősen első osztályúnak tűnnek annak ellenére, hogy alatta tömbök:

var nameNumber: ;
nameNumber = ;
var = nameNumber;

Type Alias

A TypeScript kényelmes szintaxist biztosít olyan típusjelölések nevének megadásához, amelyeket több helyen is szeretnénk használni. Az aliasokat a type SomeName = someValidTypeAnnotation szintaxissal hozzuk létre. Egy példát az alábbiakban mutatunk be:

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

A interface-től eltérően szó szerint bármilyen típusjelölésnek adhatunk típus alias-t (hasznos például union és intersection típusokhoz). Íme még néhány példa, hogy megismerkedjünk a szintaxissal:

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

TIP: Ha szükséged van a típusmegjelölések hierarchiájára, használj interface-et. Használhatók implements és extends

TIP: Egyszerűbb objektumstruktúrákhoz (mint Coordinates) csak azért használjunk típus alias-t, hogy szemantikus nevet adjunk nekik. Akkor is, amikor szemantikus neveket akarsz adni az Union vagy Intersection típusoknak, a Type alias a megfelelő megoldás.

Összefoglaló

Most, hogy elkezdheted a JavaScript kódod nagy részének annotálását, belevethetjük magunkat a TypeScript Type Systemben elérhető összes hatalom aprólékos részleteibe.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.