--- title: TypeScript You are my type of value tags: frontend, javascript, typescrypt robots: noindex, nofollow author: Julien Noyer --- # You are my type of value... *Mise en place du principe de Test driven Development en Javascript* ![](https://i.imgur.com/NKEfw4J.png) > &copy; [Julien Noyer](https://www.linkedin.com/in/julien-n-21219b28/) - All rights reserved for educational purposes only --- <br> ## Combattre le bug par le test Tous les développeurs qui ont déjà travaillé sur un projet de grands taille savent qu’ils doivent réserver entre 70 et 80 pourcent de son temps pour la pratique la plus frustrante de leur métier : les tests unitaires. Le pilotage de projet par le test, ou Test driven Development (TDD), répond en partie à la problématique en plaçant les tests dès le début du développement, ce qui permet de gagner beaucoup de temps, mais induit néanmoins de coder des fonctions de test avant de créer les fonctions du programme, ce qui peut allonger considérablement le temps de production. ![](https://i.imgur.com/0AeLyDG.png) Le principe de test n’est pas nouveau, dès que les premières lignes de codes ont été tapées, il a fallu les tester, mais à l’origine, il n’était pas à la charge du développeur. ## Le feu ça brûle et l’eau ça mouille La plupart des langages de programmation intègrent la notion de typage qui permet d’une certaine manière de contraindre des variables ou des fonctions. Cette notion manque au JavaScript, ce qui induit un temps d’écriture de test plus long lorsque l’on utilise ce langage. Pour palier à ce manque, Microsoft a développé un “Super Set” de JavaScript qui, associé aux nouveautés de la version ES6, ajoute un ensemble de techniques pour typer un programme et ainsi réduire le temps passé à tester du code. ![](https://i.imgur.com/m2IxF6N.png) L’utilisation de TypeScript ne supprime pas la nécessité de tester un programme, mais apporte des solutions pour définir précisément le comportement des éléments qui composent un programme. --- # Travailler avec TypeScript Le TypeScript n’est pas un nouveau langage, mais une surcouche de JavaScript, le principe et d’écrire un fichier au format ".ts" qui sera compiler en JavaScript pour pouvoir être utilisé dans une page Web ou dans une application. Pour commencer à coder en TypeScript il faut donc configurer un environnement de développement spécifique pour intégrer TypeScript dans un environnement de travail spécifique. ## Configuration du dossier de travail Dans un premier temps, vous devez créer un dossier contenant deux sous-dossiers, “typings” et un “js”, ainsi qu’un fichier “package.json”. ``` MyES6proj - js - typings - package.json ``` <br> ## Installer le transpiller Pour commencer, il faut installer en global le transpiller qui permet de compiler le code TypeScript. ``` npm install -g --save-dev typescript ``` > `--g` : Installation en global > `--save-dev` : Ajouté TypScript en dépendance de développement Toutes les options de TypeScript sont disponibles sur typescriptlang.org. ## Configuration du compilateur Une fois TypeScrpt installé, ajouter un script dans votre fichier package.json pour configurer le compileur. ```json= "scripts": { "build": "tsc typings/* --outDir js -w --pretty" }, ``` > `-w` : Compliation du/des fichier/s à la vollée > `--pretty` : Affichage des erreurs simplifié ## Compilation des fichiers Tous les fichiers TypeScript du dossier “typings” seront compilés en JavaScript dans le dossier “js” en tapant la commande suivante dans votre terminal : ``` npm run build ``` ## Le principe de typage Le principal avantage du TypeScript tient dans son nom : en plus d'associer un nom et une valeur à une variable, nous pouvons définir le type de la variable. Cette notion de typage est présente dans de nombreux langages de programmation, notamment le Java, mais était très compliqué en ES5. Le TypeScript propose une solution plus rapide à mettre en place et qui répond à la problématique de Test Driven Developement. Le typage d’une variable en TypeScript ce fait à l’aide du signe “:” suivie du type de la variable entre le nom et la valeur de la variable. ```javascript= /* Lorsqu’une valeur est assignée à une variable, la valeur définie le type de la variable */ let firstName = `Abdel` firstName = 38 /* A la créaion d’une variable, il faut définir son type de la façon suivante : variable: Type */ let age: string age = `Carole` age = 17 /* Le compileur indique que la valeur `38` n’est pas assignable à la variable `firstName` => Type ‘38’ is not assignable to type ‘string’. */ firstName = 38 /* Le compileur indique que la valeur `Carole` n’est pas assignable à la variable `age` => Type ‘”Carole”’ is not assignable to type ‘number’. */ age = `Carole` ``` ## Typer un tableau et ses valeurs Contrairement à des variables classiques, un tableau reçoit plusieurs variables différentes qui peuvent être également de types différents. La définition du type d’un tableau et de ces valeurs ce fait de la même manière que pour des variables classiques, mais si les types de valeurs sont différents il faut tous les définir. ```javascript= /* Les valeurs du tableau doivent toutes être de type `string` */ let firstArray: Array<string> firstArray = [`Abdel`, `Carole`, `Louis`] /* En séparant les valeur par un pipe il est possible de définir plusieur types de valeur. */ let secondeArray: Array<string | boolean> secondeArray = [true, `Carole`, `Louis`] /* Le mot clé `any` permet de ne pas définir de type */ let thirdArray: Array<any> thirdArray = [true, `Carole`, 38] /* En utilisant le mot clé `ReadonlyArray` le tableau devient une constante */ let fourthArray: ReadonlyArray<number> = [3, 10] fourthArray.push = 16 // Erreur : fourthArray est une constante ``` > Pour un tableau à type de valeur unique, il est également possible de déclarer la variable de la façon suivante : **let firstArray: String[]** ## Typer une fonction et ses paramétres Les fonctions peuvent également être typées, que ce soit au niveau du retour de la fonction comme des paramètres qui la compose. Pour des fonctions contenant un grand nombre de paramètres, il est conseillé d’utiliser un objet associé à une interface que nous verrons dans les pages suivantes. ```javascript= /* Il est indiqué à la création de la fonction qu’elle doit renvoyer une valeur de type string */ function sayHello(): string { return `Hello World` } // La valeur du retour de la fonction est bien une string sayHello() === `Hello World` // true function isPair(x: number, y: number): string { if( typeof x === 'number' && typeof y === 'number' { return 'La somme de x + y est', x + y } } // Une valeur de type string n’est pas accèptée en paramètre isPair(5, 2) === `La somme de x + y est 7` // true isPair(5, `2`) // Argument of type ‘”2”’ is not assignable ``` ## Typer le callback d’une fonction Certaines fonctions utilisent en paramètre une fonction de callback pour qu’elle s’exécute à la fin du traitement de la fonction principale. En TypeScript, il faut définir la valeur du callback et celle du retour de la fonction de callback. ```javascript= /* Le paramètre est typé de la même manière que les autres mais il faut également typer le retour de la fonction */ function twice(names: Array<string>, callback: () => string): number{ return names.length } // Création d’un tableau typé let users: Array<string> = ['Carole', 'Abdel', 'Lisa'] /* Les paramètres de la fonction principale sont disponibles dans la fonction de callback */ twice(users, () => { return 'Liste des utilisateurs :', users }) ``` > Le principe des fonctions de **callback en paramètre n’est pas spécifique à TypeScrypt**, il est question ici du typage de la fonction de callback en TypeScript. ## Typer objet avec une interface Proche du modèle objet (constructeur), les interfaces sont principalement utilisées dans le cadre de fonctions ayant en paramètre un objet. Plutôt que de typer chacune des propriétés de l’objet dans la parenthèse de la fonction, nous créons une interface réutilisable qui s’en charge. ```javascript= /* Une interface se présente sous la forme d’un objet dont les paramètres sont typés */ interface User { fullName: string, age: number, // Il est possible de rendre un paramètre constant readonly isMajor: boolean, skills: Array<string> } /* Une fois créée, l’interface est utilisée comme un type de variable ce qui allège l’écriture de la finction */ function createUser(object: User): string { return 'Création d’un nouvel utilisateur' } /* Il est recommandé de créer une variable qui utilise l’interface plutôt que de directement renseigner l’objet dans la fonction. */ let newUser: User = { fullName: 'Sophia', age: 27, isMajor: true, skills: ['ES6', 'TypeScript'] } // Le paramètre isMajor n’est pas modifiable newUser.isMajor = false // Erreur : isMajor est une constante // Lorsque tout est typé, la fonction ne peut que s’exécuter correstement createUser(newUser) ``` ## Etendre une interface Comme pour les classes que nous verrons dans les pages suivantes, il est possible de créer des interfaces qui intègrent d’autres interfaces ce qui est très utile pour séparer le code d’un programme. Cette technique permet une maintenance facilité et une réutilisation plus rapide du code lorsque les interfaces sont exportées depuis un fichier et importer dans ceux qui les utilisent. ```javascript= /* Les interface sont séparées par type de données */ interface UserInfos { userName: string, age: number } interface SkillsLevel { es6: number, ts: number } /* L’interface User intégre dans sa construction les paramètres des interfaces UserInfos et SkillsLevel */ interface User extends UserInfos, SkillsLevel { isMajor: boolean } /* Utilisation de l’interface étendue */ let newUser = <User>{} // Définitions des valeurs des paramètres newUser.userName = `Steve` newUser.es6 = 6 newUser.isMajor = true ``` ## Les classes en TypeScript Depuis la version ES6, les classes sont apparues dans la programmation JavaScript qui en manquait le cisellement. Il est donc à présent possible de développer des programmes complexes organisés par classes et TypeScript apporte des solutions pour les configurer correctement. ```javascript= /* Les paramètres peuvent être de plusieurs types (public, static, private, protected) selon leur niveau d’accessibilité. */ class Users{ public firstName: string static numOfUsers: number = 0 private _nickname: string /* Le constructeur Permet d’ajouter des valeurs dès l’instanciation d’un objet. */ constructor(userName: string){ this.firstName = userName // Permet d’ajouter des valeurs dès l’instanciation d’un objet. Users.numOfUsers++ } /* Les méthodes De plusieurs type comme les paramètres */ userInfo(): string { return `My name is ${this.firstName}` } static howManyUsers(): number { return Users.numOfUsers } /* Getter et setter Pour définir la valeur d’un paramètre de type private il faut utiliser les méthodes get et set */ get nickname(): string { return this._nickname } set nickname(pseudo: string){ this._nickname = pseudo } } // Instanciation de l’objet let newUser = new Users(`John`) // Le setter est utilisé comme un paramètre publique newUser.nickname = `The Turtle` // Un paramètre static est accessible via la classe Users.numOfUsers === 1 ``` ## Etendre une Classe Les classes offrent une multitude de possibilités en terme de programmation, mais l’erreur la plus classique lorsqu’on les utilise est d’écrire des classes trop volumineuse. La logique de programmation fonction et de séparer un maximum le code pour permettre une maintenance plus efficace. Partant de cette logique, il est recommandé d’écrire des classes et des sous-classes qui ont de comportements spécifiques. ```javascript= /* Cette classes peut contenir autant de variables et de méthode que nécessaire */ class Vehicle{ static totalVehicle: number = 0 constructor(private name: string){} // Création d’une méthode statique static howManyVehicle(): number { return Vehicle.totalVehicle } } /* Etendre une classe */ class Car extends Vehicle { public carName: string constructor(name: string){ /* La méthode super Cette méthode permet de faire référence au constructeur de la classe Vehicle */ super(name) this.carName = name } } // Instanciation de l’objet let newCar = new Car(`Fiat 500`) /* La fonction `howManyVehicle()` est directement accessible sur la classe Car */ Car.howManyVehicle() // 1 ```