1. Introduction

Le TypeScript est un langage de programmation open-source développé par Microsoft. Il a été conçu par Anders Hejlsberg, également concepteur du langage C#.

Le but premier de TypeScript est de rendre plus facile et plus fiable l’écriture de code en JavaScript pour des applications de grande ampleur.

Le langage se présente comme un sur-ensemble du JavaScript avec notamment l’apport d’un typage statique optionnel des variables et des fonctions, la création de classes et d’interfaces, la création de namespaces et de modules.

Cet article présentera de façon succincte les principaux ajouts de TypeScript par rapport à JavaScript comme le typage, les classes, et la modularité, sachant que pour ceux connaissant déjà JavaScript, l’apprentissage de TypeScript ne devrait être qu’une simple formalité.

2. installation

Pour commencer à expérimenter avec le TypeScript vous pouvez utiliser le playground. Si vous souhaitez utiliser TypeScript pour vos projets vous pouvez installer le transpiler via npm :

npm i -g typescript

Cette installation vous donnera accès à la commande tsc qui vous permettra de transpiler votre code en JavaScript (ES3, ES5 ou ES2015).

tsc index.ts

Si vous souhaitez transpiler pour le web il vous faudra passer par webpack ou browserify avec l’utilisation de plugin ou de loaders.

3. Typage

Comme son nom l’indique le TypeScript va vous permettre de définir le type de vos variables, paramètres et retours de fonctions.

3.1 Variables:

Le principal apport du langage TypeScript, celui qui justifie le nom même du langage, est la possibilité d’associer, facultativement, un type à une donnée.

Le principal apport du langage TypeScript, celui qui justifie le nom même du langage, est la possibilité d’associer, facultativement, un type à une donnée.

var pi: number;
var message: string;
var flag: boolean;
var joker: any;

Dans l’exemple ci-dessus, quatre variables sont déclarées sans être initialisées à l’aide d’un type dont la signification est explicite.

  • La variable pi a pour type number, un nombre entier ou flottant.
  • La variable message a pour type string, une chaîne de caractères.
  • La variable flag a pour type boolean, un booléen qui peut prendre la valeur true ou false.
  • La variable joker a pour type any, qui est le type par défaut qu’attribue TypeScript à une variable globale s’il ne parvient pas à déterminer son type lors de sa déclaration.

Bien entendu, il est possible d’initialiser une variable au moment de sa déclaration comme on peut le voir ci-dessous :

var pi = 3.14; // number
var message = "Bonjour !"; // string
var flag = true; // boolean
var joker = null; // any

Lors de la première initialisation d’une variable, TypeScript en infère automatiquement le type sans qu’il soit nécessaire de le mentionner explicitement.

3.2 Fonctions

Il est courant qu’une fonction renvoie un certain résultat. Le langage TypeScript permet de préciser le type du résultat attendu lors de la déclaration de la fonction.

Par défaut et en l’absence d’instruction return, le type du résultat d’une fonction est void, c’est-à-dire aucun résultat.

function triple(n: number): number {
  return 3 * n;
}

La fonction triple ci-dessus est déclarée comme prenant un paramètre de type number et renvoyant une valeur de type number.

3.3 Fonction anonyme fléchée

Un autre apport notable de TypeScript à JavaScript est sa nouvelle manière de définir une fonction anonyme qui peut être dénommée ici notation « fléchée » (arrow function) en raison de l’utilisation du symbole =>.

function alertMsg(msg: string) {
  this.msg = msg;
  this.timer = setInterval(
    () => {
      alert(this.msg);
    },
    500);
}

La fonction anonyme fléchée est définie dans cet exemple en premier paramètre de l’appel à setInterval. À gauche du symbole => doit être mentionnée la liste de paramètres entre parenthèses, et à droite du symbole =>, le corps de la fonction anonyme entre accolades.

L’avantage par rapport à l’actuelle norme de JavaScript (ECMAScript 5), est que la notation fléchée ne change pas la valeur de contexte du mot-clé this à l’intérieur de la fonction anonyme. Cela évite donc l’utilisation d’une variable intermédiaire servant à propager la valeur de this à l’intérieur de la fonction anonyme. Par exemple, la ligne de code précédente aurait pu être transcrite ainsi en JavaScript actuel :

function alertMsg(msg: string) {
  this.msg = msg;
  var _this = this;
  this.timer = setInterval(
    function () {
      alert(_this.msg);
    },
    500);
}

Cette nouvelle notation plus concise sera utile en particulier pour les fonctions callback appelées de façon asynchrone.

Il convient aussi de noter que la norme ECMAScript 6, si elle est approuvée, reprendra cette notation ; TypeScript permettant ainsi de se familiariser en avance avec ces fonctions anonymes fléchées.

4. Les Classes

Avec l’ES2015 le JavaScript supporte l’utilisation du mot clef class. Le TypeScript pousse les choses plus loin en permettant de gérer la visibilité des propriétés et la gestion des méthodes statiques.

class Demo {

    private factor

    constructor (factor: number) {
        this.factor = factor
    }

    public multiplie (n: number): number {
        return n * this.factor
    }

    static salut (): string {
        return 'Salut'
    }

}

Il est aussi possible de déclarer des accesseurs et mutateurs afin de mieux controler ce qui rentre et sort de votre objet.





class Color {

    private _color: string

    public constructor (color) {
        this._color = color 
    }

    set color (color) {
        this._color
    }

    get color () {
        if (this._color === 'rouge') {
            return 'vert'
        } else {
            return this._color
        }
    }

}

let c = new Color('rouge')
console.log(c.color) // vert

5. Interface

Une interface peut être vue tout d’abord comme une sorte de contrat minimum que doit respecter une structure de données en termes d’attributs et de méthodes. Cette structure de données peut être un objet {…} ou une classe.

Définition d'interfacesSélectionnez
interface I1 {
    a: number;
}

interface I2 {
    b: string;
}

L’interface I1 ci-dessus indique que la structure de données implémentant I1 doit avoir à minima un attribut nommé a de type number. L’interface I2 indique que la structure de données l’implémentant doit avoir à minima un attribut nommé b de type string.

Une interface est considérée comme un type à part entière, ce qui signifie qu’il est possible de définir une fonction qui prendrait un paramètre de type I1 comme l’exemple ci-dessous :

function fct(x: I1) {
    alert(x.a);
}

Cette fonction fct pouvant être appelée en passant en paramètre un objet ayant au moins un attribut nommé a :

fct({ a: 20, z: -1 });

Un autre intérêt d’une interface, c’est qu’elle peut être considérée comme une classe n’ayant que des méthodes abstraites (ou pas de méthode du tout). Cela permet dans un langage comme TypeScript ne gérant que l’héritage simple, de se rapprocher du concept de l’héritage multiple, une classe pouvant implémenter (implements) plusieurs interfaces comme le montre l’exemple ci-dessous :

class C implements I1, I2 {
    a: number;
    b: string;
    
    constructor(a: number, b: string) {
        this.a = a;
        this.b = b;
    }
}

Une instance de cette classe C pourrait tout à fait être passée en paramètre de notre fonction fct définie plus haut.

var c = new C(15, "bonjour");
fct(c);

Enfin, comme nous venons de le voir, une interface pouvant être considérée comme une classe abstraite, il est possible de faire hériter une interface d’une autre à l’aide du mot-clé extends :

interface I3 extends I2 {
  c: boolean;
}

Dans l’exemple ci-dessus, la nouvelle interface I3 dérive de l’interface I2 définie plus haut en ajoutant un attribut c de type boolean.

6. Les Namespaces

Les namespaces vous permettent d’organiser les variables dans un groupe donné afin d’éviter les problèmes d’écrasement des variables.

namespace Grafikart {
    export let var1 = 3
    let var2 = 4
    export class Demo { }
}
Grafikart.var1 // 3
Grafikart var2 // Erreur, cela n'existe pas en dehors du module
let d = new Grafikart.Demo() // Objet de type Grafikart.Demo

7. Les modules

Les modules se présentent comme des namespaces que l’on va pouvoir isoler dans un fichier séparé. Le principe est relativement similaire.





// demo.ts
export let var1 = 3
let var2 = 4
export class Demo { }

// index.ts
import { var1, Demo } from './demo'
var1 // 3

Je n’ai ici que survolé l’ensemble de possibilités du TypeScript, n’hésitez pas à parcourir la documentation pour obtenir plus d’informations.