De nos jours, le développement d’une application web peut difficilement se passer du langage Javascript. L’hégémonie de ce langage ne fait plus de doute et sa communauté est l’une des plus importantes dans le monde du développement web, ce qui est surement dû à sa flexibilité intrinsèque. Cependant, il possède certaines limites quand il s’agit de développer des applications complexes. Vous l’avez compris, dans cet article nous allons introduire TypeScript.

Nous verrons dans un premier temps ce qu’est le TypeScript puis, dans deuxième un temps, les fonctionnalités que ce langage apporte par rapport au Javascript. Nous aborderons ensuite ses différents concepts clés pour enfin finir par les avantages et inconvénients ressentis au cours de son utilisation.

 

TypeScript, Qu’est-ce que c’est ?

logo typescriptLe TypeScript est un langage de programmation développé par Microsoft en 2012. Son ambition principale est d’améliorer la productivité de développement d’applications complexes.

C’est un langage open source, développé comme un sur-ensemble de Javascript. Ce qu’il faut comprendre par là, c’est que tout code valide en Javascript l’est également en TypeScript.

Cependant, le langage introduit des fonctionnalités optionnelles comme le typage ou encore la programmation orientée objet. Pour pouvoir bénéficier de ces fonctionnalités aucune librairie n’est requise. Il suffit d’utiliser l’outil de compilation de TypeScript pour le transpiler (C’est le fait de compiler le code source d’un langage en un autre langage) en Javascript. Ainsi, le code exécuté sera un équivalent Javascript du code TypeScript compilé.

 

Installation et configuration de TypeScript

Il existe deux possibilités pour installer les outils nécessaires pour TypeScript :

Si vous avez Visual Studio 2015 Update 3, Visual Studio 2017 ou encore Visual Studio code, TypeScript est installé par défaut. Voici la commande à exécuter pour installer TypeScript avec NPM :

npm install -g typescript

 

Ci-dessous, un code Javascript valide dans un fichier TypeScript, identifié par l’extension .ts.

 

Afin de pouvoir exécuter ce programme, il faut d’abord le compiler grâce à la commande suivante :

tsc greeter.ts

 

Un fichier greeter.js sera alors généré dans le même dossier que le fichier greeter.ts.

 

À partir de là, il vous suffit de référencer le fichier Javascript dans la page html pour exécuter le programme.

 

Voilà, vous venez de créer votre première application en TypeScript ! Mais quelle différence avec une application Javascript me direz-vous ? À ce stade, aucune ! Et c’est là l’une des forces du TypeScript.

En effet, étant donné que le TypeScript est un sur-ensemble du Javascript, il peut être intégré de façon partielle dans un projet déjà en Javascript sans trop de difficulté.

Dans la prochaine partie, nous allons utiliser une des fonctionnalités phares du TypeScript, le typage statique.

 

Quelques types de bases en TypeScript

Comme vous le savez peut-être, Javascript est un langage non fortement typé mais dynamique. Le type des données n’est identifié qu’à l’exécution du programme. On peut ainsi modifier le type des données à la volée au cours de l’exécution.

 

Comme le montre l’exemple ci-dessus, une même variable, au cours du programme, peut stocker tantôt un nombre, tantôt une chaîne de caractères ou enfin une fonction. Cela a pour conséquence d’offrir une grande flexibilité aux développeurs sur la manière de développer leur application. Le revers de la médaille de cette souplesse est qu’elle peut être la cause d’un nombre de bugs important lorsque le type des données est mal maîtrisé. Dès lors, la seule façon d’identifier les bugs est d’exécuter le code.

TypeScript introduit la notion d’un typage un peu plus fort que pour le langage Javascript. Ce typage se manifeste par l’ajout de plusieurs types de bases ainsi qu’un typage statique.

Rappelons qu’un langage est dit de typage statique quand celui-ci vérifie les types des variables à la compilation, alors qu’un langage dit de typage dynamique, effectue cette vérification à l’exécution.

 

Syntaxe du typage

De façon générale, la déclaration de variables typées en TypeScript se fait de la manière suivante :

 

Dans l’exemple ci-dessous, les 2 premières déclarations de variables sont typées explicitement et la dernière l’est implicitement. À noter également que certains IDE peuvent vous aider à identifier le type de vos données assez facilement en survolant la variable qui stocke la donnée. Très pratique pour les projets volumineux à condition de bien déclarer les types de façon explicite.

 

Typage par déduction

C’est le mécanisme mis en place par le compilateur TypeScript pour identifier le type d’une variable. Lorsque le compilateur rencontre la première occurrence d’une variable, il va tenter d’en déduire son type par rapport à l’utilisation de la variable et donc supposer que toutes les autres occurrences de cette dernière auront le même type.

 

Boolean

C’est surement le type le simple. Vous pouvez le déclarer de deux façons :

 

Number

Typescript stocke les nombres en variables flottantes comme en Javascript.

let anInt: number = 6;

let decimal: number = 2.9;

let hex: number = 0xa5d2;

 

Les données de type binaires et octets sont également déclarées, le type number et ce depuis ECMAScript 2015.

let binary: number = 0b1010;

let octal: number = 0o762;

 

String

Là encore, comme avec Javascript, la variable de type string se déclare de la même façon. On peut utiliser de simples quotes, les doubles quotes et l’écriture par template avec les accents graves (Ctrl+Alt+7 ou Alt Gr +7 pour les claviers francophones).

 

Dans l’exemple suivant, on définit une fonction greeter qui attend un paramètre de type string et qui retourne une valeur de type string.

 

Lorsque l’on tente d’utiliser la fonction greeter avec un paramètre de type number, voici le message d’erreur que l’on reçoit lors de la compilation.

greeter_string.ts:9:56 – error TS2345: Argument of type ‘number’ is not assignable to parameter of type ‘string’.

 

9 document.getElementById(“display”).innerHTML = greeter(thisYeah);

 

A noter, que ce retour est très souvent proposé à la volée par les IDEs supportant le TypeScript.

Introduction à Typescript

Array

Encore une subtilité, l’écriture du Javascript est entièrement reprise en TypeScript. Du fait qu’il existe cette notion, il est possible de déclarer un array d’un type spécifique en ajoutant des crochets“[ ]” juste après le nom du type. Ou encore, il est possible d’utiliser une écriture générique, le type générique Array.

var names: string[] = [“Pierre”,”Paul”,”Jaques”];

var otherNames: Array<string> = [“Pierre”,”Paul”,”Jaques”];

 

Any

Ce type est particulier. C’est le type qui se rapproche le plus du typage dynamique du Javascript. En effet, n’importe quel autre type de données peut être affecté à une variable de type any.   Ce type est particulièrement pratique dans le cas d’utilisation de librairie tierce où n’existe pas de fichier de déclaration mais aussi pour des appels ajax.

 

Void

Ce type est souvent utilisé pour déclarer le type de retour d’une fonction qui ne renvois rien. Bien qu’il soit possible d’avoir une variable de type void, je n’ai pas eu l’occasion d’utiliser ce type dans ce cas-là.

 

Enum

Une petite nouveauté assez sympa est l’enum. Il permet d’écrire de façon plus lisible des données numériques et d’en comprendre le sens rapidement. Cela évite d’avoir des valeurs magiques un peu partout.

 

La syntaxe de enum est la même que celle du c#.

 

Par défaut, la première valeur de l’enum sera 0, toutefois il est possible de préciser la valeur de chaque élément de l’enum.

En survolant le nom de la valeur de l’enum avec le curseur il est possible de voir sa valeur numérique réelle.

 

Le casting explicite

Dans les langages fortement typés, on a parfois besoin d’expliciter le type d’un objet. C’est là que le casting entre en jeu. Pour cette opération, TypeScript propose 2 syntaxes. La première consiste à ajouter any devant la variable le type souhaité entre les symboles “<” et “>”.

 

La seconde consiste à faire précéder la variable par le mot-clé “as” suivi du type souhaité.

var myOtherObject = {id:2, name:”Peter”} as any;

 

Attention toutefois à ne pas trop abuser du casting en “any”, car il peut très vite conduire aux travers liés au type du Javascript mentionné un peu plus tôt.

 

Les fonctions dans TypeScript

Les fonctions dans TypeScript s’écrivent quasiment de la même façon que dans Javascript avec les types. Reprenons la fonction greeter évoquée précédemment.

 

En analysant rapidement cette fonction, on peut constater qu’elle accepte en paramètre une chaîne de caractères et retourne également une chaîne de caractères. Nous pouvons dès lors intégrer ces caractéristiques dans la signature la fonction de la façon suivante :

 

Dans le cas où notre fonction aurait des paramètres optionnels, il suffit d’ajouter après le nom du paramètre un point d’interrogation.

Il est possible d’obtenir le même résultat avec des paramètres initialisés ce qui donne :

 

Interfaces

L’interface nous offre un mécanisme permettant de définir des conditions (propriétés et/ou méthodes) requis pour un objet.

 

Cette interface est une représentation simplifiée d’une personne. Pour qu’un objet satisfasse cette interface, il doit contenir au moins toutes les propriétés et méthodes de cette interface.

Ci-dessous, se trouve un exemple d’utilisation avec la méthode greeter qui accepte en paramètre que des objets qui respectent l’interface “IPerson”.

 

Si l’objet ne respecte pas l’interface, alors le compilateur indiquera les éléments manquants. Ici la propriété “lastname” n’est pas définie.

 

Pour pouvoir utiliser la variable “invalidPerson”, il est possible de compléter la définition de la variable ou modifier l’interface en rendant la propriété “lastname” optionnelle en ajoutant un point d’interrogation après le nom de la variable, comme ci-dessous.

interface IPerson{

firstName: string;

lastName?: string;

}

 

Les classes dans TypeScript

La classe est la notion qui définit un objet, elle est l’un des concepts clés de la programmation orientée objet avec l’interface. Ces dernières sont utilisées en tandem au travers de structures appelées “design pattern” dont l’objectif est de résoudre des problèmes spécifiques. Ci-dessous un exemple de classe.

 

Dans cet exemple nous avons défini une classe “Personnage”. Pour accéder aux variables de classe, on utilise le mot-clé “this”.

 

Les modules

Un module est ce qu’en .NET on appellerait une assembly ou namespace. C’est un regroupement logique de classes et d’interfaces qui permet de structurer un projet et de le rendre plus propice aux changements.

Le module se déclare à l’aide du mot-clé “module”. Ci-dessous un exemple de déclaration et d’utilisation d’un module simple.

 

Ici, la méthode “greeting” sans paramètres est accessible dans toute l’application au travers de Module1 alors que la méthode “greeting” avec paramètres n’est accessible que dans le fichier où elle est déclarée. Le module s’utilise comme suivant :

 

Les modules peuvent aussi bien exposer des classes que des fonctions, des constantes ou des interfaces.

 

Les fichiers de déclaration

C’est le fichier qui contient l’ensemble des signatures de méthode d’une librairie. Il permet entre autres, d’alimenter l’auto-complétion et surtout d’avoir rapidement l’API complète d’une librairie. Il n’est donc plus nécessaire de connaître par cœur l’API des librairies.

La source principale des fichiers de déclaration se trouve dans ce repository git : https://github.com/DefinitelyTyped/DefinitelyTyped. Vous y trouverez un très grand nombre de fichiers de déclaration des librairies connues. Sachez que ces fichiers de déclaration sont mis à jour par la communauté, il peut donc y avoir des décalages entre la version de la librairie et celle du fichier de déclaration.

 

Introduction à Typescript

 

Ici, nous souhaitons utiliser lodash ainsi que le fichier de déclaration associé dans notre application que nous installons grâce aux commandes ci-dessus. Notez la différence de version entre la librairie et le fichier de déclaration.

 

Introduction à Typescript

 

Introduction à Typescript

 

L’installation du fichier de déclaration permet de bénéficier de l’auto-complétion. Plutôt pratique lorsque l’on travaille avec des grosses librairies. Si vous recherchez le fichier de déclaration d’une librairie vous pouvez utiliser le site suivant: https://aka.ms/types

 

Cas d’utilisation d’un code legacy Javascript en TypeScript

De la même façon, il est possible de commencer à utiliser du TypeScript sur un projet en Javascript. Pour cela, il suffit de créer les fichiers TypeScript dans un dossier à part et de les compiler dans votre dossier de déploiement. Si des interactions sont nécessaires entre les fichiers en TypeScript et en Javascript, alors on peut envisager l’utilisation d’un fichier de déclaration de type spécifique pour notre code Javascript.

Ci-dessous un exemple simple d’un code TypeScript qui utilise du code legacy en Javascript.

 

TypeScript Legacy

  • legacy.js contient notre code legacy
  • App.ts contient notre nouveau code TypeScript
  • Legacy-typing.d.ts contient la définition des types de l’ensemble des éléments que l’on souhaite utiliser dans notre TypeScript

 

La première ligne référence le fichier de déclaration qui contient la définition de LegacyGreeter.

 

On déclare un module dans lequel on définit une interface de correction aux éléments que l’on souhaite utiliser pour du code legacy. Puis on déclare une variable globale du même type que l’interface que l’on a définie dans notre module.

 

Ci-dessus, le code legacy qui sera appelé lors de l’exécution.

De cette façon, le TypeScript peut évoluer sans modifier le Javascript, ce qui permet une migration plus maîtrisée du Javascript au TypeScript.

 

Les avantages et inconvénients d’utiliser TypeScript

Ci-dessous, j’ai recensé quelques avantages et inconvénients de l’utilisation du TypeScript sur un projet.

 

Les avantages

  • Langage typé
  • Compilation en différentes versions ECAMScript à partir de la version 3
  • De nombreux outils sont disponibles
  • Un langage orienté objet avec l’introduction du typage, de l’héritage ou encore les notions de public et private
  • La transition du Javascript vers le Typescript peut se faire progressivement par l’introduction au fur et à mesure de types
  • La transition inverse très simple grâce à la transpilation en ECAMScript

 

Les inconvénients

  • Le code exécuté doit être compilé au préalable
  • Le code a une syntaxe plus lourde
  • Les fichiers de déclaration des librairies ne sont pas toujours disponibles ou à jour
  • Typescript ne corrige pas les travers du Javascript, il en limite certains impacts en amont

 

Conclusion

TypeScript est un langage qui permet de raccourcir le temps de développement en introduisant des fonctionnalités de la programmation orientée objet. Le compilateur est d’une aide précieuse pour repérer rapidement les erreurs car il réduit le délai entre écriture du code et identification d’erreurs grâce notamment au typage.

À noter que le transpilage du TypeScript en Javascript peut réduire la barrière à l’entrée de l’usage de langage script pour des développeurs backend, délègue la gestion des subtilités du Javascript aux outils et assure un contrôle sur la compatibilité de l’application avec les différents navigateurs sous condition.

 

Sources