Apprendre les différentes fonctionnalités de TypeScript

Pour réagir au contenu de ce tutoriel, un espace de dialogue vous est proposé sur le forum. 14 commentaires Donner une note  l'article (5)

Article lu   fois.

L'auteur

Profil Pro

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Barista part III

I-A. TypeScript et ses fonctionnalités


Cliquez pour lire la vidéo


Le cycle Barista utilise le langage TypeScript, toutefois jusqu’ici nous n’avons que très peu utilisé ce langage à bon escient. En effet, nous avons codé comme si nous étions sous JavaScript, il est temps que cela cesse !

Cependant, il est probable que vous ne soyez pas encore à l’aise avec TypeScript. Pourquoi l’utiliser ? Quels avantages apporte-t-il ? Comment l’utiliser ? Vous aurez bientôt toutes les réponses à ces questions.

I-B. TypeScript, c’est quoi ?

TypeScript est un langage de programmation libre et open source développé par Microsoft qui a pour but d’améliorer et de sécuriser la production de code JavaScript. C’est un surensemble de JavaScript (c’est-à-dire que tout code JavaScript correct peut être utilisé avec TypeScript). Le code TypeScript est transpilé en JavaScript, pouvant ainsi être interprété par n’importe quel navigateur web ou moteur JavaScript.

TypeScript permet un typage statique optionnel des variables et des fonctions, la création de classes et d’interfaces, l’import de modules, tout en conservant l’approche non contraignante de JavaScript. Il supporte la spécification ECMAScript 6.

I-C. Installer TypeScript

Même si TypeScript est déjà installé au sein du projet Barista, il est possible que vous souhaitiez l’utiliser en dehors de ce projet, voici la marche à suivre afin de procéder à son installation.

TypeScript n’est pas un langage directement disponible sur le système, il n’est pas non plus interprété directement au sein du navigateur, comme JavaScript. Pour l’utiliser, nous avons besoin de l’installer sur la machine.

Il existe deux façons d’installer TypeScript :

  • en installant Visual Studio et le plugin TypeScript ;
  • en passant par le gestionnaire de paquets de node.js, npm :
 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    #Permet d'installer TypeScript au sein du projet courant
    #(dans le dossier node_modules)
    npm install TypeScript

    #Ou alors, on peut utiliser la méthode suivante qui permet d'installer
    #TypeScript de façon globale sur la machine
    npm install -g TypeScript

    #Puis taper la commande suivante pour obtenir le numéro de version 
    tsc -v

I-D. La transpilation

À ne pas confondre avec « transpiration » (bon j’étais obligé de la faire). La transpilation (ou transcompilation) est en fait une étape que l’on pourrait qualifier de pseudo compilation + traduction. Je m’explique, en gros, le principe de base d’un compilateur est d’analyser votre code source, d’opérer tout un tas de vérifications, etc. Pour finalement traduire le code en langage machine (le fameux code binaire).

TypeScript fonctionne à l’aide d’un programme nommé tsc qui fait la même chose, à ceci près qu’il ne traduit pas le code en binaire, mais en JavaScript! C’est pour ça que l’on dit que TypeScript est un surensemble de JavaScript, car tout code JavaScript est aussi du TypeScript, en vérité à la fin tout est retraduit en JavaScript.

Ce qui signifie que :

  • TypeScript n’apporte que du sucre syntaxique à JavaScript ;
  • les possibilités de TypeScript ne peuvent aller au-delà des capacités de JavaScript (puisqu’à la fin on transpile tout vers du JavaScript ;
  • tout code JavaScript est un code TypeScript valide.

Pour transpiler, il vous suffit d’ouvrir un terminal et de taper la commande suivante :

 
Sélectionnez
    # Ici on transpile le fichier monfichier.ts et l'on 
    # obtient ainsi un fichier équivalent, traduit en JavaScript
    tsc monfichier.ts

Maintenant que l’on a bien compris ce qu’est TypeScript, passons à la suite.

I-E. Le typage de données

TypeScript doit son nom à l’une de ses fonctionnalités les plus utiles, à savoir le support du typage statique de données. Le typage statique, contrairement au typage dynamique (qui est aussi supporté) permet d’effectuer ce que l’on appelle du type checking à la compilation.

En gros, tsc va vérifier, comme le ferait un compilateur C ou C++, que les données que l’on manipule correspondent bien aux types de données déclarés. Ce qui nous évite de découvrir ce genre d’erreurs une fois le programme lancé.

JavaScript est à la base, un langage interprété, le fait de laisser un outil comme tsc vérifier le type de données revient à faire les vérifications de l’interpréteur, mais avant l’exécution du code, et du coup on ne pousse pas en production un code défectueux (en tout cas pas au niveau du type de données manipulées).

Les types de données de base supportés par TypeScript sont les suivants (liste non exhaustive) :

  • Boolean : une simple valeur pouvant être vraie (true) ou fausse (false );
  • Number : un nombre flottant (ex. : 1.5) ;
  • String : une chaîne de caractères (ex. : "Hello World") ;
  • Any : un type désignant « n’importe quel type de données », équivalent du type object en JavaScript ;
  • Void : un type désignant du vide, rien, aucune valeur, souvent utilisé pour préciser qu’une fonction/méthode ne retourne pas de valeur (on attend du vide, donc rien) ;
  • Enum : un type de données permettant de créer son propre type de données customisé avec un choix prédéfini dans les valeurs (ex. : enum Color {Red, Green, Blue}) ;
  • Array : un tableau pouvant contenir toutes sortes d’éléments (ex. : [10,true, "google"] ). On peut également définir le type de données d’un tableau (ex. : let tab:Array;) ;
  • Null and Undefined : équivalent des types null et undefined JavaScript.

Il est important de noter qu’il est recommandé de faire appel à l’inférence de type, qui est moins verbeuse et est un mécanisme assez central en TypeScript. Pour les besoins de notre cours, nous emploierons un typage fort explicite, mais je vous encourage vivement à aller jeter un œil à la documentation sur l’inférence de type.

Pour plus de détails sur les types de données en général, rendez-vous sur la documentation en ligne du langage TypeScript.

I-F. Les variables et les constantes

En TypeScript, on n’emploie plus le mot-clé var pour déclarer une variable, mais les mots-clés let et const. Le mot-clé const est utilisé, comme son nom l’indique, pour déclarer une valeur constante, ç.-à-d. une valeur ne pouvant être modifiée, si vous essayez de modifier une constante, une erreur à la compilation est levée. Le mot-clé let est quant à lui utilisé pour déclarer une valeur variable, ç.-à-d. une valeur capable de changer au cours de la durée de vie de votre programme.

Contrairement à JavaScript, qui n’est pas typé, le TypeScript l’est lui, comme son nom l’indique. Il est donc utile de préciser le type de données que l’on souhaite stocker au sein de la variable (ou de la constante) à l’aide de la syntaxe.

 
Sélectionnez
1.
2.
3.
4.
    // constante, ne peut être modifiée
    const LIGHT_SPEED:string = "299 792 458 m / s";
    // variable, peut être modifiée
    let msg:string = "Hello World";

I-G. Templates Strings

Les « templates strings » permettent d’insérer plus facilement des valeurs de variables au sein d’une chaîne de caractères, celles-ci peuvent également être définies sur plusieurs lignes. Il s’agit d’une nouveauté de la norme ES6 et TypeScript la supporte également.

 
Sélectionnez
1.
2.
3.
    let jedi = {surname:"Obiwan", name:"Kenobi"}; 
    let msg = `${jedi.name} ${jedi.surname} is the Jedi Master`;
    console.log(msg);

I-H. Les fonctions

En TypeScript comme en JavaScript, les fonctions sont incontournables. Il s’agit de blocs d’instructions répétables que l’on peut appeler (on dit invoquer) autant de fois que nécessaire. Les fonctions TypeScript, contrairement aux fonctions JavaScript, précisent le type de données qu’elles renvoient, et si elles ne renvoient rien, alors le type de retour est void (du vide).

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
    // les paramètres sont typés, et le type de la donnée 
    // retournée également à l'aide de la syntaxe suivante:
    function sum( a:number, b:number ):number{
        return a + b;
    }

    // quand une fonction ne retourne aucune donnée
    // alors on le précise en utilisant le type "void"
    function notif( msg:string ):void{
        alert(msg);
    }

    // les fonctions anonymes sont également utilisables, comme en JS
    let anonymous:Function = function():void{
        console.log("I am an anonymous function");
    };

    // on peut invoquer une fonction anonyme comme en JS
    anonymous();

I-I. Les fonctions fléchées

En TypeScript comme en JavaScript ES6, les fonctions fléchées sont supportées, bien entendu le typage des paramètres et En TypeScript comme en JavaScript ES6, les fonctions fléchées sont supportées, bien entendu le typage des paramètres et de la donnée de retour est à ajouter au sein de la version TypeScript. Il est également possible de spécifier des valeurs par défaut aux paramètres. Les fonctions fléchées ont également l’avantage de préserver le contexte this dans lequel elles sont déclarées. La donnée de retour est à ajouter au sein de la version TypeScript. Il est également possible de spécifier des valeurs par défaut aux paramètres. Les fonctions fléchées ont également l’avantage de préserver le contexte dans lequel elles sont déclarées.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
    // fonction fléchée anonyme avec valeur de paramètre par défaut
    let hello = (param_user: string = "user"): void => {
        console.log("Hello", param_user);
    };

    hello(); // invoquons cette fonction

    // les fonctions fléchées anonymes préservent le contexte
    class Gandalf {
        name: string = "Gandalf";
        introduce = () => {
            console.log("Hello my name is", this.name);
        }
    }

    // testons notre code
    new Gandalf().introduce();

I-J. Les boucles

En TypeScript, les boucles fonctionnent comme en JavaScript :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
    let i:number = 10;

    // une boucle for classique en TypeScript
    for( i = 0; i < 10; i ++){
        console.log(i);
    }

    // une boucle while classique en TypeScript
    i = 10;
    while( --i > -1 ){
        console.log(i);
    }

    // une boucle do while classique en TypeScript
    i = -1;
    do{
        if( i == -1 ){
            i = 10;
        }
    }while( --i > -1)

I-K. Les tableaux

TypeScript, comme JavaScript, permet de travailler avec des tableaux de valeurs. À la différence qu’en Typescipt, les tableaux (si on le souhaite) peuvent être typés ; ce qui signifie qu’ils ne peuvent contenir qu’un seul type de données. La déclaration de type pour les tableaux peut s’écrire de deux façons :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
    // première façon de déclarer un tableau typé
    let notes:number[] = [
        0,10,12,7,8,20,13,15
    ];

    // seconde façon de déclarer un tableau typé
    let notes2:Array<number> = [
        0,10,12,7,8,20,13,15
    ];

I-L. Les enums

TypeScript nous permet de créer et d’utiliser des enums. Les enums permettent au développeur de créer un lot de constantes et de les regrouper de façon à former un nouveau type de données.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
    // créons un type de données "Direction"
    // qui peut prendre 4 valeurs différentes

    enum Direction { Up = 1, Down = 2, Left = 3, Right = 4 };

    let haut: Direction = Direction.Up;
    let bas: Direction = Direction.Down;
    let gauche: Direction = Direction.Left;
    let droite: Direction = Direction.Right;

    console.log(haut, bas, gauche, droite);

I-M. Modules

À partir de ECMAScript 2015 (ES6), JavaScript introduit le concept de modules, et bien entendu, ce concept est supporté en TypeScript. Les modules sont exécutés au sein de leur propre portée, et non pas au sein de la portée globale. Cela signifie que les variables, fonctions, classes, etc. déclarées au sein d’un module ne sont pas visibles en dehors du module à moins qu’elles ne soient explicitement exportées à l’aide du mot-clé export. De fait, pour utiliser un élément exporté, au sein d’un module différent, il faut utiliser le mot-clé import.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
    export function toto(){
        console.log("toto est beau");
    }

    import {toto} from './ts_modules_1';
    toto();

I-N. Programmation orientée objet (POO)

La programmation orientée objet est un style de programmation nous permettant de représenter des concepts informatiques sous forme d’objets. Pour conceptualiser un objet, nous avons besoin de plusieurs outils directement intégrés au langage. Il existe également plusieurs façons de « coder objet », JavaScript est un langage orienté objet par prototypage, mais TypeScript lui émule le comportement d’un langage orienté objet par classe. Il est important de retenir qu’un objet possède plusieurs caractéristiques :

  • un objet possède des propriétés, c.-à-d. des variables qui lui appartiennent en propre, la portée de ces propriétés peut être publique, protégée ou privée ;
  • un objet possède également des méthodes, c.-à-d. des fonctionnalités (fonctions) qui lui appartiennent en propre, la portée de ces méthodes peut être publique, protégée ou privée ;
  • dans un langage orienté objet par classe, un objet peut hériter d’un autre objet ;
  • un objet peut prendre plusieurs formes et redéfinir ses propriétés héritées.

Et il ne s’agit ici que des caractéristiques minimales, c.-à-d. celles qui définissent base d’un langage orienté objet, on parle des principes d’encapsulation, d’héritage et de polymorphisme.

I-O. Les classes

Voyons tout de suite comment coder une classe en TypeScript.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
    class Hero{
        // une propriété peut être publique, protégée ou privée
        public name:string;
        public power:string;

        // la fonction constructrice est invoquée automatiquement 
        // à la création d'un nouvel objet 
        constructor( 
            param_name:string, 
            param_power:string
        ){
            // on attribue à nos propriétés les valeurs passées 
            // en paramètres
            this.name = param_name;
            this.power = param_power;
        }

        // une méthode peut être publique, protégée ou privée
        public sayMyName():void{
            console.log(this.name);
        }

        public sayMyPower():void{
            console.log(this.power);
        }
    }

    let myHero:Hero = new Hero("Batman", "Being rich");
    myHero.sayMyName();

I-P. Héritage

Maintenant, voyons comment une classe peut hériter d’une autre en TypeScript.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
class Personnage { 
   // on veut transmettre cette propriété à nos enfants, on utilise donc protected 
   protected name: string; 
   // on veut transmettre cette propriété à nos enfants, on utilise donc protected 
   protected lifepoint: number;    
   constructor(param_name: string, param_lifepoint: number) {
        this.name = param_name;
        this.lifepoint = param_lifepoint;
    }

    //  on doit pouvoir demander à un personnage s'il est mort
    // sans être soi-même un personnage, la portée est donc publique
    public isDead(): boolean {
        // si le nombre de points de vie est inférieur 
        // ou égal à 0 alors le personnage est mort
        if (this.lifepoint <= 0) {
            return true;
        } 
        else {
            return false;
        }
    }

    public sayMyName():void{
        console.log(this.name);
    }
}

class Wizard extends Personnage{
    constructor( ){
        // on peut invoquer le constructor de la classe parente à l'aide de "super"
        super("Gandalf", 100);

        //... maintenant un nouvel objet de type wizard se nommera toujours 
        // Gandalf et aura 100 points de vie
    }

    // on réécrit la méthode sayMyName définie par le parent 
    // et héritée de celui-ci.
    public sayMyName():void{
        //, mais on peut toujours invoquer l'ancienne "version" de la méthode
        // toujours à l'aide de "super"
        super.sayMyName();

        // si on veut, on peut ajouter des opérations supplémentaires
        console.log("I am a super magician !");
    }
}

// on crée un nouveau sorcier
let gandalf:Wizard = new Wizard();
// on crée un personnage Gollum qui possède 2 points de vie 
let gollum:Personnage = new Personnage("Gollum", 2);

gandalf.sayMyName();
gollum.sayMyName();

I-Q. Conclusion

C’est tout pour ce petit tour de TypeScript ! À partir de maintenant nous allons l’utiliser de façon rigoureuse, nous typerons donc l’ensemble de nos variables et nous allons également faire en sorte de créer des objets qui vont représenter les concepts que nous manipulerons. On se dit à bientôt, devant un petit café !

II. Remerciements Developpez.com

Nous tenons à remercier l’auteur Nicolas Legrand. Nos remerciements également à Yahiko pour la relecture technique, Malick pour la mise au gabarit et ClaudeLELOUP pour la relecture orthographique.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2020 Nicolas Legrand. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.