A TypeScript programozási nyelv

Típusok, típuskonstrukciók

Típusrendszer

TypeScript típusrendszere statikusan típusos, de ennek a használata opcionális a nyelvben. Mivel a TypeScript fordítója Javascript kódot generál, ezért a statikus típusellenőrzés fordítási időben történik. Ezzel modellezi a Javascript dinamikus, futásidőbeli típuskiértékelését. Ezzel a megoldással nincs fölösleges futásidejű overhead a program futásakor.
A nyelvben megkülönböztetünk primitív (primitive types) és objektum típusokat (object types). Minden típus az Any típus altípusa. (Megjegyzés: tervek között szerepel az enumerációk és a generikus típusok bevezetése is).

Elemi típusok

Any típus

Javascript-beli értékek reprezentálására szolgál. Minden típus altípusa neki. Használata megegyezik a Javascript-ben látottakkal: bármilyen property-t, függvényt el lehet érni benne.

var x: any; //explicit megadjuk a típusát var y; //ugyanaz, mint: var y: any; var z: { a; b; }; //ugyanaz, mint: z: {a: any; b: any; } function f(x) { console.log(x); } //ugyanaz mint: f(x:any): void { /*...*/ }

Number (number) típus

Primitív típus, ami a számok tárolására szolgál a nyelvben. A nyelvben nincs külön egész, illetve valós típus, ezért minden numerikus literál ilyen típusú. Dupla pontosságú 64-bites IEEE 754 formátumú lebegőpontos számok reprezentálására szolgál.

var x: number; //explicit megadjuk a típusát var y = 0; //ugyanaz, mint: var y: number = 0; var z = 123.456; //ugyanaz, mint: z: number = 123.456; var s = z.toFixed(2); //Number interfész property-je.

String (string) típus

Primitív típus, ami a karaktersorozatok tárolására szolgál a nyelvben. Unicode UTF-16 karakterkódolást használ. A nyelvben nincs lehetőség csupán karakterek tárolására, ezért a String típus használjuk arra is.

Boolean (bool) típus

Primitív típus, ami a logikai értékek tárolására szolgál a nyelvben. Két konstans logikai értéket lehet neki adni: true, false.
A 9.0-s verzióban a bool típust elavultként jelzi, majd a fordító, a 9.1-es verziótól a bool többé nem használható, helyette boolean-t kell használni. Ennek oka az, hogy az ECMAScript-ben a Boolean hivatalosan „boolean”.

Null típus

Primitív típus. Egyetlen lehetséges értéke a null érték lehet. Nincs lehetőség direkten hivatkozni a típusra.
A Void és az Undefined típusok kivételével minden típusnak az altípusa. Ebből következik, hogy minden primitív típusú változó értékül kaphatja a null értéket is (beleértve a Number és a Boolean típusúakat is).

Undefined típus

Primitív típus. Egyetlen lehetséges értéke az undefined érték lehet. Nem lehetséges direkten hivatkozni a típusra. Minden típusnak az altípusa, így bármilyen típusú változónak értékül lehet adni az undefined értéket.

var n: number; //var n: number = undefined; var x = undefined; //var x: any = undefined; var e: Undefined; //fordítási hiba, nem lehet direkten hivatkozni a típusra!

Void (void) típus

Speciális típus, ami olyan függvények visszatérési típusát reprezentálja, amely nem tér vissza értékkel. Altípusa az Any típusnak és őstípusa az Undefined típusnak, de más típusokkal nem áll kapcsolatban. Egyetlen lehetséges érték, ami adható neki, az az undefined. Csakis függvények visszatérési értékénél használhatjuk.

String literál

A 9.0-s verziótól érhető el. A string literállok típusként való használata csak paraméter típus annotációkban megengedett, sehol máshol. A string literáll altípusa a string primitív típusnak.

Típuskonstrukciók

Tömb típus

Tömb típus egy apró különbségben tér el a Javascript-ben látott megoldástól, de azt leszámítva teljesen megegyezik a használata. A nyelv statikus típusrendszerének köszönhetően lehetőség van arra, hogy megszabja, milyen típusú értékei lehetnek a tömbben.
A 9.0-s verzióban az Array már generikus típus.
A 9.0-s verziótól nem használható a "new number[]".

var list: number[] = [1,2,3]; //Számokat tartalmazó tömb deklarációja console.log(list[0], list[1]); // 1 2 list[0] = "Hello World!"; //fordítási hiba!

Enum

A nyelv a 9.1-es verziótól tartalmazza a felsoroló típust is.

EnumDeclaration: num Identifier { EnumBodyopt }

Az enum deklarál egy enum típust és egy enum objektumot. Mindkettő a deklarációban megadott nevet kapja. Az enum típus a Number típus egy kitüntetett altípusa. Az enum objektum egy tulajdonságok halmazát tartalmazó névtelen objektum változója. Minden felsoroló típus a típusnak megfelelő értékeket deklarálja a deklaráció törzsében. Továbbá tartalmaz egy numerikus indexet a következő szignatúrával, ‘[x: number]: string’. Az azonosító nem lehet egy előredefiniált típus neve. A numerikus index szignatúra egy fordított leképezés, ami automatikusan generálódik minden enum objektumhoz. A fordított leképezés egy kényelmes módja az enum értékeinek szöveges reprezentálására. Mint például:

var c = Color.Red; console.log(Color[c]); // Kimenet: "Red"

A felsoroló tagjai

Az enum törzse nulla vagy több tagot definiál, amelyek nevesített értékei a felsoroló típusnak. Minden taghoz tartozik a primitív típus egy numerikus értéke, melyet a felsoroló deklarációjában adtunk meg. A tagok lehetnek statikus tagok illetve számított tagok is. A konstans tagoknak előre definiált konstans értékeik vannak, melyek helyettesíthetik azokat a hivatkozás helyén fordítási időben. A számított tagok esetén az értékek kiszámítása futási időben történik, azaz nem tudunk róluk semmit fordítási időben. Az enum deklarációjának törzse nulla vagy több konstans tagból áll, amelyeket követhetnek számított tagok. A konstans tagokat deklarálhatjuk egy egész literállal és a hozzá tartozó értékkel. Azonban, ha nem adunk meg egész literállt, akkor az értékhez hozzárendelődik a megelőző tag indexe plusz egy, vagy 0, ha az adott tag az első a felsorolásban. A konstans tag értéke fordítási időben értékelődik ki és helyettesítheti a tagot a rá történő hivatkozásokat generált JavaScript kódban. A számított tagokhoz megadott kifejezéseknek Any, Number vagy Enum típusúaknak kell lenniük. A számított tagok hivatkozhatnak korábban deklarált tagokra. Mivel az enum a Number altípusa, így az értékek kiszámításakor használhatóak a numerikus operátorok, mint például a bitenkénti OR.

Típuskonverziók

Lehetőség van a típuskonverzióra is, viszont csak fordítási időben ad plusz információt a fordítónak, mivel kódgeneráló figyelmen kívül hagyja.

interface A { a: number; } var a = <A>{ a: 10 };

Változók, konstansok

Változók deklarálása a var kulcsszóval történik. Opcionálisan a változó neve után kettősponttal meg lehet adni explicit a változó típusát, amit a fordító a későbbiekben figyelembe fog venni. Ha mégsem adjuk meg, akkor megpróbálja kitalálni a változó típusát. Ezt a kezdeti értékadás határozhatja meg, hogy milyen típusú is lesz. Ha nem lehet kikövetkeztetni, akkor automatikusan any típusú lesz.

var a: number; //number típusú lesz az "a" var b = 10; //típuskikövetkeztetés eredményeképpen number típusú lesz a "b" változó var c; //any típusú lesz a "c"

Típus paraméterek

A 9.0-s verziótól érhető el. A típus paramétereket a generikus típusokra való hivatkozáskor illetve generikus függvények hívásakor használjuk. A típus paraméter tulajdonképpen egy megszorítás az aktuális paraméter típusára nézve. Mivel a típus paraméter több különböző típusú argumentumot reprezentál, ezért más típusoktól eltérően bizonyos mértékű szigorításokat kell tenni. Mint például, a típus paramétert nem lehet ősosztályként vagy interface-ként használni.

Nevesített típusok

Az osztályok, interface-ek és a felsorolók a nevesített típusok. Az osztályoknak és az interface-eknek lehet típus paraméterük, ekkor ezeket generikus típusoknak hívjuk. Azokat a nevesített típusokat, amelyeknek nincs típus paraméterük, nem-generikus típusoknak nevezzük. A nevesített típusokra típus referenciákon keresztül hivatkozhatunk, amelyek megadják a típus nevét és adott esetben a típus argumentumokat is. A nevesített típusok technikailag nem típusok, csak referenciák. Ez a megkülönböztetés egyértelmű a generikus típusoknál: a generikus típusok sablonok, amelyekből több tényleges típus hozható létre típus referenciák segítségével, amelyek helyettesítik a generikus típus típus paramétereit. A generikus típusokat nem lehet megkülönböztetni a kézzel írott kifejezésektől:

interface Pair { first: T1; second: T2; } A típus referencia Pair megkülönböztethetetlen a típustól { first: string; second: Entity; }

Rekurzív generikus típusok

Generikus típusok hivatkozhatnak önmagukra direkten vagy indirekten rekurzív módon, amennyiben ez nem generálja új típustok végtelen sorát. Konkrétan egy G < T1 , T2 , … , Tn > generikus típusban és az általa hivatkozott típusokban hiba, ha a G-re hivatkozunk egy típus paraméterrel, ami tartalmazza G bármelyik típus paraméterét (Tx).

Példánytípus

Minden nevesített típushoz tartozik egy aktuális típus, ami példánytípusnak nevezünk. A nem-generikus típusoknál ez egyszerűen egy hivatkozás a típusra. A generikus típusnál, a példánytípus a típushivatkozás létrehozásával keletkezik a generikus típusból, ahol minden egyes típus argumentum megfelel egy típusparaméternek. Mivel a példánytípus használja a típusparamétereket, ezért csak ott használható, ahol a típusparaméter benne van a scope-ban, azaz a generikus típus belsejében. Egy osztály konstruktorában és a tagfüggvényeiben található típus az osztály példánytípusa.