Am acoperit principalele caracteristici ale TypeScript Type System atunci când am discutat despre De ce TypeScript?. Următoarele sunt câteva repere cheie din acea discuție, care nu au nevoie de explicații suplimentare:
-
Sistemul de tipuri din TypeScript este conceput pentru a fi opțional, astfel încât JavaScript-ul dumneavoastră să fie TypeScript.
-
TypeScript nu blochează emiterea JavaScript în prezența erorilor de tip, permițându-vă să vă actualizați progresiv JS-ul la TS.
Acum să începem cu sintaxa sistemului de tipuri TypeScript. În acest fel, puteți începe să folosiți imediat aceste adnotări în codul dvs. și să vedeți beneficiile. Acest lucru vă va pregăti pentru o scufundare mai profundă mai târziu.
După cum am menționat anterior Tipurile sunt adnotate folosind sintaxa :TypeAnnotation
. Orice este disponibil în spațiul de declarare a tipurilor poate fi folosit ca o adnotare de tip.
Exemplul următor demonstrează adnotările de tip pentru variabile, parametrii funcțiilor și valorile de returnare ale funcțiilor:
var num: number = 123;function identity(num: number): number {return num;}
Tipuri primitive
Tipurile primitive JavaScript sunt bine reprezentate în sistemul de tipuri TypeScript. Aceasta înseamnă , number
, boolean
, așa cum este demonstrat mai jos:
var num: number;var str: string;var bool: boolean;num = 123;num = 123.456;num = '123'; // Errorstr = '123';str = 123; // Errorbool = true;bool = false;bool = 'false'; // Error
Array-uri
TypeScript oferă o sintaxă de tip dedicată pentru array-uri pentru a vă facilita adnotarea și documentarea codului. Sintaxa constă practic în postfixarea la orice adnotare de tip validă (de exemplu,
:boolean
). Aceasta vă permite să efectuați în siguranță orice manipulare de matrice pe care ați face-o în mod normal și vă protejează de erori precum atribuirea unui membru de tip greșit. Acest lucru este demonstrat mai jos:
var boolArray: boolean;boolArray = ;console.log(boolArray); // trueconsole.log(boolArray.length); // 2boolArray = true;boolArray = ;boolArray = 'false'; // Error!boolArray = 'false'; // Error!boolArray = ; // Error!
Interfețe
Interfețele sunt modalitatea principală în TypeScript de a compune mai multe adnotări de tip într-o singură adnotare numită. Luați în considerare următorul exemplu:
interface Name {first: string;second: string;}var name: Name;name = {first: 'John',second: 'Doe'};name = { // Error : `second` is missingfirst: 'John'};name = { // Error : `second` is the wrong typefirst: 'John',second: 1337};
Aici am compus adnotările first: string
+ second: string
într-o nouă adnotare Name
care aplică verificările de tip pe membrii individuali. Interfețele au o mare putere în TypeScript și vom dedica o întreagă secțiune modului în care le puteți folosi în avantajul dumneavoastră.
Adnotare de tip inline
În loc să creați un nou interface
puteți adnota orice doriți inline folosind :{ /*Structure*/ }
. Exemplul anterior prezentat din nou cu un tip inline:
var name: {first: string;second: string;};name = {first: 'John',second: 'Doe'};name = { // Error : `second` is missingfirst: 'John'};name = { // Error : `second` is the wrong typefirst: 'John',second: 1337};
Tipurile inline sunt excelente pentru a oferi rapid o adnotare de tip unică pentru ceva. Vă scutește de grija de a veni cu un nume de tip (potențial prost). Cu toate acestea, dacă vă treziți că puneți aceeași adnotare de tip inline de mai multe ori, este o idee bună să luați în considerare refactorizarea acestuia într-o interfață (sau un type alias
abordat mai târziu în această secțiune).
Tipuri speciale
În afară de tipurile primitive care au fost abordate, există câteva tipuri care au o semnificație specială în TypeScript. Acestea sunt any
, null
, undefined
, void
.
orice
Tipul any
deține un loc special în sistemul de tipuri TypeScript. Acesta vă oferă o portiță de scăpare din sistemul de tipuri pentru a spune compilatorului să se ducă naibii. any
este compatibil cu oricare și toate tipurile din sistemul de tipuri. Aceasta înseamnă că îi poate fi atribuit orice și poate fi atribuit la orice. Acest lucru este demonstrat în exemplul de mai jos:
var power: any;// Takes any and all typespower = '123';power = 123;// Is compatible with all typesvar num: number;power = num;num = power;
Dacă portezi cod JavaScript în TypeScript, vei fi prieten apropiat cu any
la început. Cu toate acestea, nu luați această prietenie prea în serios, deoarece înseamnă că depinde de dumneavoastră să asigurați siguranța tipurilor. Practic, îi spuneți compilatorului să nu facă nicio analiză statică semnificativă.
null și undefined
Cum sunt tratate de sistemul de tipuri depinde de steagul de compilare strictNullChecks
(vom aborda acest steag mai târziu). Atunci când sunt în strictNullCheck:false
, literalele null
și undefined
JavaScript sunt efectiv tratate de sistemul de tipuri la fel ca ceva de tip any
. Aceste literale pot fi atribuite la orice alt tip. Acest lucru este demonstrat în exemplul de mai jos:
var num: number;var str: string;// These literals can be assigned to anythingnum = null;str = undefined;
:void
Utilizați :void
pentru a semnifica faptul că o funcție nu are un tip de retur:
function log(message): void {console.log(message);}
Generics
Mulți algoritmi și structuri de date din informatică nu depind de tipul real al obiectului. Cu toate acestea, doriți totuși să impuneți o constrângere între diverse variabile. Un exemplu simplu de jucărie este o funcție care preia o listă de elemente și returnează o listă inversată de elemente. Constrângerea aici este între ceea ce este transmis funcției și ceea ce este returnat de funcție:
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; // Okayreversed = ; // Okay
Aici, practic, spuneți că funcția reverse
preia o matrice (items: T
) de un anumit tip T
(observați parametrul de tip din reverse<T>
) și returnează o matrice de tip T
(observați : T
). Deoarece funcția reverse
returnează elemente de același tip cu cele pe care le ia, TypeScript știe că variabila reversed
este, de asemenea, de tipul number
și vă va oferi siguranța tipului. În mod similar, dacă treceți un array de string
la funcția inversă, rezultatul returnat este, de asemenea, un array de string
și veți obține o siguranță de tip similară, așa cum se arată mai jos:
var strArr = ;var reversedStrs = reverse(strArr);reversedStrs = ; // Error!
De fapt, array-urile JavaScript au deja o funcție .reverse
și TypeScript folosește într-adevăr generice pentru a defini structura sa:
interface Array<T> {reverse(): T;// ...}
Aceasta înseamnă că obțineți siguranță de tip atunci când apelați .reverse
pe orice matrice, așa cum se arată mai jos:
var numArr = ;var reversedNums = numArr.reverse();reversedNums = ; // Error!
Vom discuta mai multe despre interfața Array<T>
mai târziu, când vom prezenta lib.d.ts
în secțiunea Declarații ambientale.
Union Type
În mod obișnuit în JavaScript doriți să permiteți ca o proprietate să fie unul dintre mai multe tipuri, de exemplu un string
sau un number
. În acest caz, tipul de uniune (notat cu |
într-o adnotare de tip, de exemplu string|number
) este util. Un caz comun de utilizare este o funcție care poate lua un singur obiect sau o matrice a obiectului, de exemplu:
function formatCommandline(command: string|string) {var line = '';if (typeof command === 'string') {line = command.trim();} else {line = command.join(' ').trim();}// Do stuff with line: string}
Tipul de intersecție
extend
este un model foarte comun în JavaScript în care se iau două obiecte și se creează unul nou care are caracteristicile acestor două obiecte. Un Intersection Type vă permite să utilizați acest model într-un mod sigur, așa cum este demonstrat mai jos:
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 nu are suport pentru tuple de primă clasă. În general, oamenii folosesc doar un array ca tuple. Acest lucru este exact ceea ce suportă sistemul de tipuri TypeScript. Tuplurile pot fi adnotate folosind :
etc. Un tuple poate avea orice număr de membri. Tuplurile sunt demonstrate în exemplul de mai jos:
var nameNumber: ;// OkaynameNumber = ;// Error!nameNumber = ;
Combinați acest lucru cu suportul de destructurare din TypeScript, tuplurile se simt destul de bine ca fiind de primă clasă, în ciuda faptului că sunt array-uri dedesubt:
var nameNumber: ;nameNumber = ;var = nameNumber;
Alias de tip
TypeScript oferă o sintaxă convenabilă pentru a furniza nume pentru adnotările de tip pe care doriți să le utilizați în mai multe locuri. Aliasurile sunt create folosind sintaxa type SomeName = someValidTypeAnnotation
. Un exemplu este demonstrat mai jos:
type StrOrNum = string|number;// Usage: just like any other notationvar sample: StrOrNum;sample = 123;sample = '123';// Just checkingsample = true; // Error!
În comparație cu un interface
, puteți da un alias de tip literalmente oricărei adnotări de tip (util pentru chestii precum tipurile de uniune și intersecție). Iată alte câteva exemple pentru a vă familiariza cu sintaxa:
type Text = string | { text: string };type Coordinates = ;type Callback = (data: string) => void;
TIP: Dacă trebuie să aveți ierarhii de adnotări de tip, utilizați un
interface
. Acestea pot fi utilizate cuimplements
șiextends
TIP: Utilizați un alias de tip pentru structuri de obiecte mai simple (cum ar fi
Coordinates
) doar pentru a le da un nume semantic. De asemenea, atunci când doriți să dați nume semantice tipurilor Union sau Intersection, un alias de tip este calea de urmat.
Rezumat
Acum că puteți începe să adnotați cea mai mare parte a codului dvs. JavaScript, putem trece la detaliile esențiale ale întregii puteri disponibile în Type System din TypeScript.
.