Nous avons couvert les principales caractéristiques du système de types de TypeScript en arrière lorsque nous avons discuté de Pourquoi TypeScript ? Voici quelques éléments clés de cette discussion qui n’ont pas besoin d’être expliqués davantage :
-
Le système de types de TypeScript est conçu pour être facultatif afin que votre JavaScript soit TypeScript.
-
TypeScript ne bloque pas l’émission de JavaScript en présence d’erreurs de type, ce qui vous permet de mettre progressivement à jour votre JS en TS.
Maintenant, commençons par la syntaxe du système de types de TypeScript. De cette façon, vous pouvez commencer à utiliser ces annotations dans votre code immédiatement et en voir les avantages. Cela vous préparera à une plongée plus profonde plus tard.
Comme mentionné précédemment les types sont annotés en utilisant la syntaxe :TypeAnnotation
. Tout ce qui est disponible dans l’espace de déclaration de type peut être utilisé comme une annotation de type.
L’exemple suivant démontre les annotations de type pour les variables, les paramètres de fonction et les valeurs de retour de fonction:
var num: number = 123;function identity(num: number): number {return num;}
Types primitifs
Les types primitifs JavaScript sont bien représentés dans le système de type TypeScript. Cela signifie string
, number
, boolean
comme démontré ci-dessous:
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
Tableaux
TypeScript fournit une syntaxe de type dédiée aux tableaux pour faciliter l’annotation et la documentation de votre code. La syntaxe consiste essentiellement à postfixer à toute annotation de type valide (par exemple
:boolean
). Elle vous permet de faire en toute sécurité n’importe quelle manipulation de tableau que vous feriez normalement et vous protège des erreurs comme l’affectation d’un membre du mauvais type. Ceci est démontré ci-dessous:
var boolArray: boolean;boolArray = ;console.log(boolArray); // trueconsole.log(boolArray.length); // 2boolArray = true;boolArray = ;boolArray = 'false'; // Error!boolArray = 'false'; // Error!boolArray = ; // Error!
Interfaces
Les interfaces sont le moyen principal dans TypeScript de composer plusieurs annotations de type en une seule annotation nommée. Considérez l’exemple suivant :
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};
Ici, nous avons composé les annotations first: string
+ second: string
en une nouvelle annotation Name
qui applique les vérifications de type sur les membres individuels. Les interfaces ont beaucoup de pouvoir dans TypeScript et nous consacrerons une section entière à la façon dont vous pouvez utiliser cela à votre avantage.
Annotation de type en ligne
Au lieu de créer une nouvelle interface
, vous pouvez annoter tout ce que vous voulez en ligne en utilisant :{ /*Structure*/ }
. L’exemple précédent a présenté à nouveau un type en ligne:
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};
Les types en ligne sont parfaits pour fournir rapidement une annotation de type unique pour quelque chose. Ils vous épargnent le tracas de trouver un nom de type (potentiellement mauvais). Cependant, si vous vous retrouvez à mettre la même annotation de type en ligne plusieurs fois, c’est une bonne idée d’envisager de la refactoriser en une interface (ou un type alias
couvert plus tard dans cette section).
Types spéciaux
A part les types primitifs qui ont été couverts, il y a quelques types qui ont une signification spéciale dans TypeScript. Il s’agit de any
, null
, undefined
, void
.
any
Le type any
occupe une place particulière dans le système de types de TypeScript. Il vous donne une trappe d’échappement du système de types pour dire au compilateur de se casser la gueule. any
est compatible avec tous les types du système de types. Cela signifie que n’importe quoi peut lui être attribué et qu’il peut être attribué à n’importe quoi. Ceci est démontré dans l’exemple ci-dessous :
var power: any;// Takes any and all typespower = '123';power = 123;// Is compatible with all typesvar num: number;power = num;num = power;
Si vous portez du code JavaScript vers TypeScript, vous allez être très ami avec any
au début. Cependant, ne prenez pas cette amitié trop au sérieux car cela signifie que c’est à vous d’assurer la sécurité des types. Vous dites essentiellement au compilateur de ne pas faire d’analyse statique significative.
null et undefined
La façon dont ils sont traités par le système de types dépend de l’indicateur de compilation strictNullChecks
(nous couvrons cet indicateur plus tard). Lorsqu’ils sont dans strictNullCheck:false
, les littéraux JavaScript null
et undefined
sont effectivement traités par le système de type de la même manière que quelque chose de type any
. Ces littéraux peuvent être affectés à tout autre type. Ceci est démontré dans l’exemple ci-dessous :
var num: number;var str: string;// These literals can be assigned to anythingnum = null;str = undefined;
:void
Utilisez :void
pour signifier qu’une fonction n’a pas de type de retour :
function log(message): void {console.log(message);}
Génériques
De nombreux algorithmes et structures de données en informatique ne dépendent pas du type réel de l’objet. Cependant, vous souhaitez toujours appliquer une contrainte entre diverses variables. Un exemple simple de jouet est une fonction qui prend une liste d’éléments et renvoie une liste inversée d’éléments. La contrainte ici est entre ce qui est passé à la fonction et ce qui est retourné par la fonction:
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
Ici, vous dites essentiellement que la fonction reverse
prend un tableau (items: T
) d’un certain type T
(remarquez le paramètre de type dans reverse<T>
) et retourne un tableau de type T
(remarquez : T
). Comme la fonction reverse
renvoie des éléments du même type que ceux qu’elle prend, TypeScript sait que la variable reversed
est également de type number
et vous donnera la sécurité de type. De même, si vous passez un tableau de string
à la fonction inverse, le résultat retourné est également un tableau de string
et vous obtenez une sécurité de type similaire comme indiqué ci-dessous:
var strArr = ;var reversedStrs = reverse(strArr);reversedStrs = ; // Error!
En fait, les tableaux JavaScript ont déjà une fonction .reverse
et TypeScript utilise effectivement les génériques pour définir sa structure :
interface Array<T> {reverse(): T;// ...}
Cela signifie que vous obtenez une sécurité de type lorsque vous appelez .reverse
sur n’importe quel tableau comme indiqué ci-dessous :
var numArr = ;var reversedNums = numArr.reverse();reversedNums = ; // Error!
Nous discuterons davantage de l’interface Array<T>
plus tard lorsque nous présenterons lib.d.ts
dans la section Déclarations ambiantes.
Type d’union
Plus souvent en JavaScript, vous voulez permettre à une propriété d’être l’un de plusieurs types, par exemple un string
ou un number
. C’est là que le type union (dénoté par |
dans une annotation de type, par exemple string|number
) est pratique. Un cas d’utilisation commun est une fonction qui peut prendre un seul objet ou un tableau de l’objet par exemple:
function formatCommandline(command: string|string) {var line = '';if (typeof command === 'string') {line = command.trim();} else {line = command.join(' ').trim();}// Do stuff with line: string}
Type d’intersection
extend
est un motif très commun en JavaScript où vous prenez deux objets et créez un nouveau qui a les caractéristiques de ces deux objets. Un type d’intersection vous permet d’utiliser ce motif de manière sûre comme démontré ci-dessous :
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;
Type de tuple
JavaScript n’a pas de support de tuple de première classe. Les gens utilisent généralement simplement un tableau comme un tuple. C’est exactement ce que le système de type TypeScript prend en charge. Les tuple peuvent être annotés en utilisant :
etc. Un tuple peut avoir un nombre quelconque de membres. Les tuples sont démontrés dans l’exemple ci-dessous:
var nameNumber: ;// OkaynameNumber = ;// Error!nameNumber = ;
Combinez cela avec le support de déstructuration dans TypeScript, les tuples se sentent assez de première classe malgré le fait qu’ils soient des tableaux en dessous:
var nameNumber: ;nameNumber = ;var = nameNumber;
Type Alias
TypeScript fournit une syntaxe pratique pour fournir des noms pour les annotations de type que vous souhaitez utiliser à plusieurs endroits. Les alias sont créés en utilisant la syntaxe type SomeName = someValidTypeAnnotation
. Un exemple est démontré ci-dessous:
type StrOrNum = string|number;// Usage: just like any other notationvar sample: StrOrNum;sample = 123;sample = '123';// Just checkingsample = true; // Error!
À la différence d’un interface
, vous pouvez donner un alias de type à littéralement n’importe quelle annotation de type (utile pour des choses comme les types d’union et d’intersection). Voici quelques exemples supplémentaires pour vous familiariser avec la syntaxe:
type Text = string | { text: string };type Coordinates = ;type Callback = (data: string) => void;
TIP : Si vous avez besoin d’avoir des hiérarchies d’annotations de type, utilisez un
interface
. Ils peuvent être utilisés avecimplements
etextends
TIP : Utilisez un alias de type pour les structures d’objets plus simples (comme
Coordinates
) juste pour leur donner un nom sémantique. Aussi, lorsque vous voulez donner des noms sémantiques aux types Union ou Intersection, un alias de type est la voie à suivre.
Résumé
Maintenant que vous pouvez commencer à annoter la plupart de votre code JavaScript, nous pouvons sauter dans les détails minutieux de toute la puissance disponible dans le système de type de TypeScript.