Introduction

« TypeScript, le langage compilé en JavaScript ? Mais pourquoi faudrait-il quitter JavaScript ? »

Le langage JavaScript ne manque pas d'atouts et le mieux est souvent l'ennemi du bien. Délaisser ce qui fonctionne est un risque. Et puis il existe de solides arguments en défaveur des langages construits sur JavaScript, examinons-les :

  1. La question de la pérennité des syntaxes non standard ;
  2. La problématique de l'intégration avec l'existant ;
  3. La difficulté de former ou de trouver les développeurs.

Je répondrai à ces trois questions au fil de l'exposé tout en situant TypeScript par rapport aux technologies concurrentes. Je tenterai ensuite de donner envie au lecteur d'essayer.

I. TypeScript est un choix sans risque

Avant toute chose, TypeScript n'est pas un choix dangereux pour l'équipe de développeurs qui envisage de l'adopter.

En effet, le nouveau langage fait sien le slogan de CoffeeScript : « It's just JavaScript ». Le compilateur TypeScript n'ajoute aucune dépendance à une bibliothèque JavaScript. Voilà qui contraste avec la solution proposée par Traceur dont le code compilé s'appuie massivement sur un runtime en JavaScript.

Plus encore, le développeur TypeScript se repère sans effort dans son propre code traduit en JavaScript. En vérité le code JavaScript après compilation est impeccable et pourrait être repris comme base de travail JavaScript s'il fallait un jour quitter le navire.

II. Faire coopérer TypeScript et JavaScript ?

TypeScript est un surensemble de la syntaxe JavaScript. Autrement dit, à peu de choses près, tout code JavaScript compilera en TypeScript.

TypeScript s'intègre alors naturellement dans l'écosystème JavaScript. Les bibliothèques de programmation JavaScript comme jQuery ou Modernizr sont appelées normalement depuis du code TypeScript. Et dans l'autre sens, le code TypeScript, une fois compilé, s'utilise aisément depuis du code écrit directement en JavaScript. Ainsi, les frameworks AngularJS et consorts travaillent sans faire d'histoire avec du code TypeScript compilé.

Cette intégration de TypeScript avec le Web existant est à mettre en opposition avec le langage Dart conçu comme un environnement autonome en rupture avec JavaScript et dans lequel tout est à refaire. La syntaxe de TypeScript, quant à elle, est en continuité avec celle du JavaScript. Aucun travail d'adaptation de l'existant n'est à faire et la baisse de productivité due à l'effort d'apprentissage est limitée à quelques jours, surtout si le développeur a déjà de l'expérience dans d'autres langages à objets.

III. La syntaxe TypeScript est pérenne

JavaScript a évolué depuis son invention en 1995. Le langage fut normalisé par Ecma International en 1997 sous le nom de ECMAScript. Internet Explorer 8 par exemple comprend l'ECMAScript 3. Le JavaScript interprété par les navigateurs en 2014 est ECMAScript 5.1.

Certains ajouts syntaxiques apportés par TypeScript sont une implémentation de fonctionnalités prévues dans le prochain ECMAScript 6. Par rapport aux fonctionnalités de ECMAScript 6 listées par Luke Hoban, TypeScript implémente les suivantes : Arrows, Classes, Default + Rest + Spread et Modules. Cela fait de TypeScript un langage essentiellement normalisé ce qui, au passage, lui donne l'avantage sur CoffeeScript pour ce qui est de la pérennité.

Cela implique également que le compilateur TypeScript est destiné à être simplifié. Lorsque les navigateurs implémenteront nativement ECMAScript 6, le compilateur se repliera sur les seules fonctionnalités non normalisées de TypeScript.

IV. TypeScript et Microsoft ?

TypeScript est porté par Microsoft. Ces dernières années Microsoft a opéré un tournant radical par rapport à l'open source et l'on peut s'en réjouir. TypeScript est sous licence Apache 2. En outre le compilateur TypeScript est utilisable en dehors de l'univers Microsoft, il est en effet présent depuis le début sur Node.js.

Deux éléments sont révélateurs de l'importance du projet TypeScript pour Microsoft. En premier lieu JavaScript est devenu un langage prioritaire pour Microsoft. Pour appuyer notre propos, relevons son support en natif par Windows 8, ou encore le fait que JavaScript est une porte de sortie élégante pour VBA, le vieux langage de script étant devenu une ornière depuis DotNet.

En second lieu le projet TypeScript est dirigé par Anders Hejlsberg qui n'a fait que du solide : il fut l'architecte de Turbo Pascal, de Delphi puis, chez Microsoft, de DotNet/C#.

Je suis tenté de conclure, mais c'est personnel, que TypeScript est promis à un avenir immense. Et si Microsoft ne communique pas fort sur sa technologie, c'est peut-être que l'éditeur préfère prendre le temps de travailler sur l'intégration du langage et du Web dans ses divers outils ?

… Alors, finalement, TypeScript, pourquoi pas ?

La suite de l'article est consacrée aux apports de TypeScript.

V. La programmation orientée objet et TypeScript

En JavaScript, jusqu'à l'actuel ECMAScript 5, la notion de classe n'existe pas et le développeur travaille directement sur les objets. Un mécanisme peut servir à émuler un comportement de classe : le prototype dont l'usage est malheureusement incomplet. Impossible en particulier de déclarer des membres privés dans le prototype. L'encapsulation est certes réalisable au niveau de l'objet par des closures, mais il en résulte une empreinte mémoire inutilement large et une durée d'initialisation allongée puisque chaque objet conserve alors ses propres pointeurs vers chacune des méthodes privées.

TypeScript apporte à JavaScript une programmation orientée objet classique.

Entre parenthèses je tiens à insister sur quelque chose de fondamental : les bonnes pratiques en JavaScript, dont les closures et la programmation asynchrone par callbacks, restent de bonnes pratiques en TypeScript. La syntaxe des classes ne retire rien, elle s'ajoute.

Mais trêve de bavardages. J'invite le lecteur à ouvrir sans attendre le Playground de TypeScript et à y tester le code que voici :

 
Sélectionnez
interface SayHello {
	say(name: string): void;
}
class MyFirstClass implements SayHello {
	constructor(private prefix = 'Hello') {
	}
	public say(name: string) {
		alert(this.makeMessage(name));
	}
	private makeMessage(name: string): string {
		return this.prefix + ', ' + name + '!';
	}
}
var sayToWorld = function (sh: SayHello) {
	sh.say('World');
};
sayToWorld(new MyFirstClass());

Le code est facile à comprendre. Une interface SayHello est déclarée, une classe MyFirstClass implémentant cette interface vient ensuite, puis une fonction sayToWorld est définie, qui attend une implémentation de l'interface en paramètre. Remarquez le private prefix directement comme argument du constructeur : la présence de l'accesseur est un raccourci pour déclarer la variable d'instance prefix et lui affecter la valeur du paramètre du même nom (lequel reçoit ici 'Hello' en valeur par défaut).

Les fonctionnalités apportées par TypeScript sont décrites dans le Handbook et les spécifications (PDF). L'objet de cet article n'est pas d'en faire le tour mais je recommande tout de même au lecteur de vite s'intéresser aux modules qui seront les espaces de nommage dans ECMAScript 6 et le sont déjà dans TypeScript.

Au-delà des classes et des valeurs par défaut venant de ECMAScript 6, TypeScript ajoute le typage en suffixe (d'une manière qui rappelle singulièrement la syntaxe de Hack) et les accesseurs private et public. Le mécanisme de déclaration et d'implémentation des interfaces, lié au typage, mérite une attention particulière.

VI. Les interfaces TypeScript

Les interfaces en TypeScript sont particulièrement souples. Dans le code donné ci-dessus, retirez la mention implements SayHello au niveau de la déclaration de la classe : le code reste valide. Renommez maintenant la méthode say : le compilateur relève l'erreur au niveau de l'appel à sayToWorld.

Vous pouvez même bénéficier des contrôles de typage tout en optant pour une programmation au niveau de l'objet à la manière classique de JavaScript. Par exemple ce code :

 
Sélectionnez
sayToWorld({
	'say': function (name) {
		alert('Hi ' + name + '!');
	}
}); 

Ici la classe n'est pas utilisée, la fonction sayToWorld est appelée avec un objet implémentant directement notre interface.

Notons que les interfaces, tout comme le typage et les accesseurs, n'affectent pas les performances puisqu'elles sont absentes du code JavaScript généré.

VII. Typage statique ?

Pourquoi du typage statique ? Pour simplifier la documentation nécessaire à la collaboration entre les développeurs et pour aider l'IDE. Les développeurs TypeScript bénéficient d'une aide à la saisie que leurs homologues en JavaScript leur envieraient s'ils savaient, et ce y compris sur des bibliothèques écrites en JavaScript comme jQuery. Des fichiers de définitions répertoriant de nombreuses API existantes sont en effet maintenus par l'importante communauté de DefinitelyTyped.

À savoir : le typage est vérifié au niveau de la compilation. Il est facile de le tromper, par exemple en manipulant dynamiquement les membres d'un objet.

Le typage de TypeScript est optionnel. Il n'est pas là pour restreindre la créativité du développeur et à mon avis ce ne serait pas une bonne pratique de toujours tout typer tout le temps ou encore de laisser de côté le code dynamique. En revanche, déclarer les types dans les méthodes publiques d'une classe servant d'API, ou encore dans les fonctions exportées par un module Node.js, est certainement une pratique à recommander.

TypeScript sait également induire le type à partir d'une déclaration. Par exemple, les deux instructions suivantes sont équivalentes :

 
Sélectionnez
var s = 'Hello';
 
Sélectionnez
var s: string = 'Hello';

La plus lisible, la première, est sans doute la meilleure. Dans les deux cas la variable est typée et par exemple l'instruction suivante lève une erreur :

 
Sélectionnez
s = 123; // Cannot convert 'number' to 'string'.

Si le développeur souhaite volontairement changer le type d'une variable, le « joker » any fera taire le compilateur :

 
Sélectionnez
var s: any = 'Hello';
s = 123; // ok

VIII. Comment démarrer avec TypeScript

Ça se tente ? Voici comment démarrer :

  1. Installer Node.js ;
  2. En ligne de commande, installer le compilateur TypeScript sur Node.js avec la commande npm donnée sur le site officiel ;
  3. Il vous faudra un IDE : WebStorm (il embarque une licence d'un mois pour tester), Eclipse avec le plugin pour TypeScript, ou bien sûr Visual Studio pour ceux qui l'ont ;
  4. Sous WebStorm la procédure est la suivante : créer un projet puis créer un premier fichier « .ts » avec du code TypeScript ; l'IDE propose alors spontanément d'ajouter un « Watcher » chargé de compiler TypeScript à la volée, il faut accepter puis le configurer afin qu'il ne soit appelé qu'à l'enregistrement : File → Settings → File Watchers → TypeScript (edit) → Décocher « Immediate file synchronization » ;
  5. L'apprentissage demandera un peu de lecture en anglais ; rendez-vous sur le Handbook du site officiel.

Vous êtes lancé, et le forum TypeScript vous attend.

IX. Remerciements

Ceci est mon premier article. Merci à vermine pour l'assistance sur la plateforme de publication de developpez.com, et à ced pour le repérage des petites coquilles et la fluidité du texte.