---
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*

> © [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.

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.

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
```