Tutoriels vidéos
Recent Articles
Home » Archives pour février 2018
Le JavaScript++
Publié dans
script
|
samedi 17 février 2018|
ali
TypeScript
est un langage très récent (février 2012) qui 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.
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é.
Puis, après la brève mention des principaux outils de développement utilisables avec TypeScript, nous comparerons l'approche de TypeScript avec deux autres langages similaires, CoffeeScript et Dart, et tenterons de montrer en quoi l'approche de TypeScript semble la plus viable à l'avenir.
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é.
Puis, après la brève mention des principaux outils de développement utilisables avec TypeScript, nous comparerons l'approche de TypeScript avec deux autres langages similaires, CoffeeScript et Dart, et tenterons de montrer en quoi l'approche de TypeScript semble la plus viable à l'avenir.
2. Typage
2-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.
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.
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.
Ainsi, TypeScript, contrairement à JavaScript, peut être considéré comme un langage à typage statique.
Typage explicite de variables
Sélectionnez
var
pi
:
number
;
var
message
:
string
;
var
flag
:
boolean
;
var
joker
:
any
;
- 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.
Typage implicite de variables
Sélectionnez
var
pi =
3
.
14
;
//
number
var
message =
"
Bonjour
!
"
;
//
string
var
flag =
true
;
//
boolean
var
joker =
null
;
//
any
Ainsi, TypeScript, contrairement à JavaScript, peut être considéré comme un langage à typage statique.
2-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.
La fonction triple ci-dessus est déclarée comme prenant un paramètre de type number et renvoyant une valeur de type number.
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.
Typage d'une fonction
Sélectionnez
function
triple
(
n
:
number
):
number
{
return
3
*
n;
}
3. Classe
La notion de classe introduite dans TypeScript anticipe la prochaine évolution de JavaScript (ECMAScript 6).
Comme on peut le voir dans l'exemple ci-dessus, une classe Animal y est définie d'une façon proche de la plupart des langages orientés objet.
La classe Animal possède ici un attribut (name), elle définit un constructeur (constructor) et une méthode (shout). Son instanciation se fait à l'aide de l'opérateur new comme ceci :
De pair avec la notion de classe, TypeScript implémente la notion d'héritage simple par l'utilisation du mot-clé extends.
L'extension de la classe Animal de l'exemple précédent pourrait se faire ainsi :
Cette nouvelle classe Lion ajoute un nouvel attribut sex à la classe Animal et redéfinit la méthode shout.
Puisque toutes les classes définies dans TypeScript sont considérées comme de nouveaux types, la classe Lion est du type Lion, et en vertu de l'héritage est aussi du type Animal.
En remarque, malgré cet apport orienté objet à la syntaxe initiale de JavaScript, il faut avoir conscience que les limitations intrinsèques de JavaScript se reflètent également dans TypeScript. Par exemple, la notion d'attribut privé (private) d'une classe qui existe dans la plupart des langages orientés objet, bien que syntaxiquement présente dans TypeScript, n'est pas véritablement restrictive dans la mesure où un attribut privé pourra malgré tout être utilisé en dehors de sa classe avec une approche dynamique.
Définition d'une classe
Sélectionnez
class
Animal {
name
:
string
;
constructor
(
name
:
string
) {
this
.
name =
name;
}
shout
(
):
string
{
return
"
...
"
;
}
}
La classe Animal possède ici un attribut (name), elle définit un constructeur (constructor) et une méthode (shout). Son instanciation se fait à l'aide de l'opérateur new comme ceci :
Instanciation d'une classe
Sélectionnez
var
animal =
new
Animal
(
"
pokemon
"
);
L'extension de la classe Animal de l'exemple précédent pourrait se faire ainsi :
Héritage
Sélectionnez
class
Lion extends
Animal {
sex
:
string
;
constructor
(
name
:
string
,
sex
:
string
) {
super
(
name);
this
.
sex =
sex;
}
shout
(
):
string
{
return
"
Rooooaarrr!
"
}
}
Puisque toutes les classes définies dans TypeScript sont considérées comme de nouveaux types, la classe Lion est du type Lion, et en vertu de l'héritage est aussi du type Animal.
En remarque, malgré cet apport orienté objet à la syntaxe initiale de JavaScript, il faut avoir conscience que les limitations intrinsèques de JavaScript se reflètent également dans TypeScript. Par exemple, la notion d'attribut privé (private) d'une classe qui existe dans la plupart des langages orientés objet, bien que syntaxiquement présente dans TypeScript, n'est pas véritablement restrictive dans la mesure où un attribut privé pourra malgré tout être utilisé en dehors de sa classe avec une approche dynamique.
4. 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.
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 :
Cette fonction fct pouvant être appelée en passant en paramètre un objet ayant au moins un attribut nommé a :
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 :
Une instance de cette classe C pourrait tout à fait être passée en paramètre de notre fonction fct définie plus haut.
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 :
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.
Définition d'interfaces
Sélectionnez
interface
I1 {
a
:
number
;
}
interface
I2 {
b
:
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 :
Interface en tant que type
Sélectionnez
function
fct
(
x
:
I1) {
alert
(
x.
a);
}
Objet implémentant une interface
Sélectionnez
fct
(
{
a
:
20
,
z
:
-
1
}
);
Classe implémentant deux interfaces
Sélectionnez
class
C implements
I1,
I2 {
a
:
number
;
b
:
string
;
constructor
(
a
:
number
,
b
:
string
) {
this
.
a =
a;
this
.
b =
b;
}
}
Sélectionnez
var
c =
new
C
(
15
,
"
bonjour
"
);
fct
(
c);
Héritage entre interfaces
Sélectionnez
interface
I3 extends
I2 {
c
:
boolean
;
}
5. 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 =>.
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 :
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.
Fonction anonyme fléchée
Sélectionnez
function
alertMsg
(
msg
:
string
) {
this
.
msg =
msg;
this
.
timer =
setInterval
(
(
) =
>
{
alert
(
this
.
msg);
}
,
500
);
}
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 :
Équivalent JS de la fonction anonyme fléchée
Sélectionnez
function
alertMsg
(
msg
:
string
) {
this
.
msg =
msg;
var
_this =
this
;
this
.
timer =
setInterval
(
function
(
) {
alert
(
_this.
msg);
}
,
500
);
}
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.
6. Modularité
La modularité en TypeScript est un sujet qui peut rapidement
devenir complexe et nécessiterait un article en soi. Dans ce chapitre,
nous nous contenterons de n'évoquer que les principales techniques.
6-1. Référencement de fichiers
TypeScript introduit de nouvelles techniques de modularisation
devenues nécessaires par le typage statique et par l'héritage de
classes. Parmi ces techniques de modularisation, le référencement d'un
fichier TypeScript externe est peut-être la plus simple.
Elle consiste à inclure de façon statique en tout début de fichier, un autre fichier source TypeScript contenant des déclarations nécessaires au compilateur afin qu'il en déduise entre autres les types et les héritages.
À noter que le référencement ressemble un peu aux #include des langages C/C++.
C'est cette approche qui est en général adoptée pour utiliser des bibliothèques JavaScript déjà existantes via les fichiers de déclaration .d.ts.
Sur certains environnements intégrés de développement comme Visual Studio, le référencement peut se faire implicitement, sans avoir besoin de mentionner le fichier contenant les dépendances de déclarations, même si un référencement explicite peut faciliter la documentation des dépendances entre fichiers sources.
Ce référencement permet très simplement de bénéficier à l'intérieur du fichier source appelant, partageant le même espace de nommage, des déclarations de variables, de fonctions ou de classes présentes dans le fichier référencé.
L'utilisation du référencement de fichiers se fait généralement pour les applications côté client où dans la page HTML il sera nécessaire soit de référencer via la balise <script> l'ensemble des fichiers JavaScript générés (c.f. index1.htm), soit de référencer le fichier issu de la concaténation éventuellement minifiée (.min.js) de ces fichiers JavaScript (c.f. index2.htm).
L'inconvénient de cette approche est que cela peut engendrer des conflits de nommage entre deux variables globales, fonctions ou classes pouvant porter la même appellation. Pour remédier à ce problème, TypeScript propose la notion de module explicite.
Elle consiste à inclure de façon statique en tout début de fichier, un autre fichier source TypeScript contenant des déclarations nécessaires au compilateur afin qu'il en déduise entre autres les types et les héritages.
source.ts
Sélectionnez
//
/
<reference
path="module.ts"/>
C'est cette approche qui est en général adoptée pour utiliser des bibliothèques JavaScript déjà existantes via les fichiers de déclaration .d.ts.
Sur certains environnements intégrés de développement comme Visual Studio, le référencement peut se faire implicitement, sans avoir besoin de mentionner le fichier contenant les dépendances de déclarations, même si un référencement explicite peut faciliter la documentation des dépendances entre fichiers sources.
Ce référencement permet très simplement de bénéficier à l'intérieur du fichier source appelant, partageant le même espace de nommage, des déclarations de variables, de fonctions ou de classes présentes dans le fichier référencé.
L'utilisation du référencement de fichiers se fait généralement pour les applications côté client où dans la page HTML il sera nécessaire soit de référencer via la balise <script> l'ensemble des fichiers JavaScript générés (c.f. index1.htm), soit de référencer le fichier issu de la concaténation éventuellement minifiée (.min.js) de ces fichiers JavaScript (c.f. index2.htm).
index1.htm
Sélectionnez
<!
DOCTYPE
html
>
<
html
lang
=
"
fr
"
>
<
head>
<script src
=
"
module.js
"
>
</
script>
<script src
=
"
source.js
"
>
</
script>
<
/
head>
<
body>
...
<
/
body>
<
/
html>
Dans l'exemple ci-dessus, on suppose que les fichiers module.js et source.js sont le résultat de la compilation en JavaScript des fichiers module.ts et source.ts.
index2.htm
Sélectionnez
<!
DOCTYPE
html
>
<
html
lang
=
"
fr
"
>
<
head>
<script src
=
"
source-module.min.js
"
>
</
script>
<
/
head>
<
body>
...
<
/
body>
<
/
html>
Dans l'exemple ci-dessus, on suppose que le fichier source-module.min.js est la concaténation du fichier module.js suivi du fichier source.js.
Par souci de performance, la seconde solution consistant à
fusionner les fichiers JavaScript résultants est en général privilégiée.
C'est pourquoi les fichiers reliés par référencement (dans l'exemple module.ts) au fichier source principal (dans l'exemple source.ts)
peuvent être qualifiés de modules internes, par opposition aux modules
externes reliés par une autre méthode et que nous verrons un peu plus
loin.L'inconvénient de cette approche est que cela peut engendrer des conflits de nommage entre deux variables globales, fonctions ou classes pouvant porter la même appellation. Pour remédier à ce problème, TypeScript propose la notion de module explicite.
6-2. Module explicite
En TypeScript chaque fichier source est implicitement un module.
Il est possible de déclarer explicitement un module, ce qui basiquement créera un espace de nommage permettant de spécifier les variables, fonctions, interfaces ou classes pouvant être importées dans un autre fichier, par exemple via référencement. Un module explicite est introduit par le mot-clé module.
Dans l'exemple ci-dessus, le module M exporte, c'est-à-dire rend accessible, les éléments suivants :
Par exemple, dans ce même fichier source, l'instruction suivante utilisant la variable id est valide :
alors que l'instruction ci-dessous utilisant la variable temp n'est pas valide :
Il est possible de déclarer explicitement un module, ce qui basiquement créera un espace de nommage permettant de spécifier les variables, fonctions, interfaces ou classes pouvant être importées dans un autre fichier, par exemple via référencement. Un module explicite est introduit par le mot-clé module.
module.ts
Sélectionnez
module
M {
var
temp =
"
bonjour
"
;
export
var
id =
0
;
export
function
fct
(
) {
… }
export
interface
I {
a
:
number
;
}
export
class
C implements
I {
a
:
number
;
}
}
- la variable id ;
- la fonction fct ;
- l'interface I ;
- et la classe C.
Par exemple, dans ce même fichier source, l'instruction suivante utilisant la variable id est valide :
module.ts
Sélectionnez
alert
(
M.
id);
module.ts
Sélectionnez
alert
(
M.
temp);
//
erreur
6-3. Importation de modules externes
Alors que précédemment la responsabilité de l'espace de nommage
était au niveau du module appelé, forçant l'utilisateur à réutiliser
l'espace de nommage du module concerné, il est possible de transférer la
responsabilité de l'espace de nommage au niveau du fichier source
appelant à l'aide des mot-clés import et require.
Reprenons l'exemple de la section précédente, mais cette fois sans créer d'espace de nommage via le mot-clé module :
Ainsi défini, ce fichier module2.ts peut être importé dans un autre fichier, qu'on supposera pour l'exemple présent dans le même répertoire que module2.ts, de la manière suivante :
Ci-dessus, le symbole m ainsi défini via le mot-clé import est un nouvel espace de nommage englobant les éléments exportés du fichier module2.ts, sans avoir recours au référencement de fichiers via la syntaxe /// <reference>.
Cette technique de modularisation est surtout pratiquée pour des applications côté serveur (e.g. Node.js) où les différents fichiers n'ont pas vocation à être combinés en un seul fichier final JavaScript. C'est la raison pour laquelle on peut parler de modules externes dans ce cas.
Reprenons l'exemple de la section précédente, mais cette fois sans créer d'espace de nommage via le mot-clé module :
module2.ts
Sélectionnez
export
var
id =
0
;
export
function
fct
(
) {
… }
export
interface
I {
a
:
number
;
}
export
class
C implements
I {
a
:
number
;
}
source2.ts
Sélectionnez
import
m =
require
(
"
./module2
"
);
m.
id+
+
;
Cette technique de modularisation est surtout pratiquée pour des applications côté serveur (e.g. Node.js) où les différents fichiers n'ont pas vocation à être combinés en un seul fichier final JavaScript. C'est la raison pour laquelle on peut parler de modules externes dans ce cas.
7. Typage générique
Le typage générique ajoute un niveau d'abstraction en rendant les
types paramétrables, que ce soit dans une fonction, une classe ou une
interface, sachant qu'au moment de l'appel effectif à cette fonction ou à
cette classe, le type devra être explicitement défini.
Le typage générique est surtout utile en TypeScript lorsqu'il s'agit d'assurer la cohérence du typage entre différents éléments. Par exemple, si on considère un tableau de nombres, on pourrait souhaiter disposer d'une fonction de concaténation assurant de concaténer ce tableau de nombres avec un autre tableau de nombres et non avec un tableau de chaînes de caractères ou d'autres choses. Par contre, on pourrait souhaiter que cette même fonction de concaténation puisse s'appliquer sur deux tableaux de chaînes de caractères ou autres, sans avoir besoin de réécrire une nouvelle fonction pour chaque type traité. C'est à ce moment-là qu'intervient le typage générique.
La syntaxe du typage générique est tout ce qu'il y a de classique
pour les habitués de C++, C# ou de Java. Le type générique (dans
l'exemple T) est déclaré entre chevrons <>, puis est utilisé comme un type ordinaire.
L'exemple montre la concaténation de deux tableaux de nombres (resultNumbers) et de deux tableaux de chaînes de caractères (resultStrings), et montre aussi qu'il n'est pas possible de concaténer un tableau de nombres avec un tableau de chaînes de caractères (resultError1 et resultError2) sous peine de lever une erreur.
Le typage générique est donc différent du type any puisqu'une fonction de concaténation entre deux tableaux de type any[] n'aurait pas levé d'erreur au niveau de la compilation comme l'indique le quatrième résultat de l'exemple (resultAny).
Le typage générique est surtout utile en TypeScript lorsqu'il s'agit d'assurer la cohérence du typage entre différents éléments. Par exemple, si on considère un tableau de nombres, on pourrait souhaiter disposer d'une fonction de concaténation assurant de concaténer ce tableau de nombres avec un autre tableau de nombres et non avec un tableau de chaînes de caractères ou d'autres choses. Par contre, on pourrait souhaiter que cette même fonction de concaténation puisse s'appliquer sur deux tableaux de chaînes de caractères ou autres, sans avoir besoin de réécrire une nouvelle fonction pour chaque type traité. C'est à ce moment-là qu'intervient le typage générique.
Définition d'une fonction générique
Sélectionnez
function
concatenate<
T>
(
a1:
T[
]
,
a2:
T[
]
):
T[
]
{
return
a1.
concat
(
a2);
}
resultNumbers =
concatenate<
number
>
(
[
1
,
2
]
,
[
3
,
4
]
);
//
[1,
2,
3,
4]
resultStrings =
concatenate<
string
>
(
[
"
a
"
,
"
b
"
]
,
[
"
c
"
,
"
d
"
]
);
//
["a",
"b",
"c",
"d"]
resultError1 =
concatenate<
number
>
(
[
1
,
2
]
,
[
"
a
"
,
"
b
"
]
);
//
erreur
resultError2 =
concatenate<
string
>
(
[
1
,
2
]
,
[
"
a
"
,
"
b
"
]
);
//
erreur
resultAny =
concatenate<
any
>
(
[
1
,
2
]
,
[
"
a
"
,
"
b
"
]
);
//
[1,
2,
"a",
"b"]
L'exemple montre la concaténation de deux tableaux de nombres (resultNumbers) et de deux tableaux de chaînes de caractères (resultStrings), et montre aussi qu'il n'est pas possible de concaténer un tableau de nombres avec un tableau de chaînes de caractères (resultError1 et resultError2) sous peine de lever une erreur.
Le typage générique est donc différent du type any puisqu'une fonction de concaténation entre deux tableaux de type any[] n'aurait pas levé d'erreur au niveau de la compilation comme l'indique le quatrième résultat de l'exemple (resultAny).
8. Outils
Bien que TypeScript soit d'abord un compilateur installable via Node.js,
pour être exploité à son plein potentiel, il est recommandé qu'il soit
associé à un environnement intégré de développement comme Visual Studio, WebStorm ou éventuellement Eclipse.
Pour tester de petits morceaux de codes (snippets), il peut être intéressant d'utiliser le site TypeScript.io fonctionnant de façon similaire à JsFiddle.
Aussi, la page de test mise à disposition par Microsoft peut également être utile pour voir immédiatement la transcription en JavaScript d'un code TypeScript.
Pour tester de petits morceaux de codes (snippets), il peut être intéressant d'utiliser le site TypeScript.io fonctionnant de façon similaire à JsFiddle.
Aussi, la page de test mise à disposition par Microsoft peut également être utile pour voir immédiatement la transcription en JavaScript d'un code TypeScript.
9. TypeScript et les autres
Après cet aperçu concernant le « sucre syntaxique » de TypeScript,
intéressons-nous au modèle de développement de ce langage
comparativement à ses principaux concurrents que sont CoffeeScript
(décembre 2009) et Dart (2011).
9-1. Maturité
On constate tout d'abord que TypeScript est le plus jeune des
trois, n'étant apparu qu'en 2012. Ce retard de maturité est encore
visible dans la mesure où la version de production 1.0 n'a été
disponible que cette année 2014. Cependant, force est de constater qu'à
l'instar de Google avec Dart, Microsoft et son concepteur restent très
impliqués dans l'évolution de TypeScript, ce qui ne peut que rassurer
ses utilisateurs. Concernant TypeScript, il est raisonnable de tabler
sur deux à trois évolutions majeures par an.
9-2. Code source▲
Tout comme CoffeeScript et Dart, le code source du compilateur TypeScript est disponible en Open source (Licence Apache 2), sur le compte GitHub de Microsoft. Ce critère n'est donc pas discriminant pour évaluer la pertinence relative de ce langage sur les deux autres.
9-3. Correspondance JavaScript
La conversion de TypeScript vers le JavaScript est assez directe
et le sera encore davantage avec l'officialisation de la norme
ECMAScript 6 puisque TypeScript est un sur-ensemble de JavaScript. Il
est donc très aisé d'identifier le morceau de code TypeScript ayant
produit un morceau de code JavaScript. Cette forte correspondance
(voulue) entre TypeScript et JavaScript permet à TypeScript de
bénéficier sans trop d'efforts aux innombrables bibliothèques, API ou
frameworks écrits en JavaScript. C'est évidemment un gros avantage.
Ce n'est pas forcément le cas des deux autres langages. La syntaxe de CoffeeScript inspirée du langage Haskell peut parfois être absconse et en tous les cas significativement différente de JavaScript pouvant rendre le débogage, l'identification entre code source et le code traduit et l'importation de codes en JavaScript natifs non triviaux. Et cela est encore plus vrai pour Dart qui emploie une syntaxe différente à celle de JavaScript en s'inspirant davantage de Java et du C++. D'autant plus que les optimisations réalisées par Dart lors de la conversion en code JavaScript peuvent significativement changer la structure du code et l'ordre des instructions.
En fin de document, on trouvera en annexe le résultat de la conversion en JavaScript d'un programme simple rédigé en trois versions : CoffeeScript, Dart et TypeScript. Le lecteur se convaincra facilement que TypeScript est syntaxiquement le langage le plus proche de JavaScript, le code source étant très similaire au code cible, tandis que dans le cas de Dart avec son code cible interminable, on peut se poser la question de son lien avec JavaScript.
Ce n'est pas forcément le cas des deux autres langages. La syntaxe de CoffeeScript inspirée du langage Haskell peut parfois être absconse et en tous les cas significativement différente de JavaScript pouvant rendre le débogage, l'identification entre code source et le code traduit et l'importation de codes en JavaScript natifs non triviaux. Et cela est encore plus vrai pour Dart qui emploie une syntaxe différente à celle de JavaScript en s'inspirant davantage de Java et du C++. D'autant plus que les optimisations réalisées par Dart lors de la conversion en code JavaScript peuvent significativement changer la structure du code et l'ordre des instructions.
En fin de document, on trouvera en annexe le résultat de la conversion en JavaScript d'un programme simple rédigé en trois versions : CoffeeScript, Dart et TypeScript. Le lecteur se convaincra facilement que TypeScript est syntaxiquement le langage le plus proche de JavaScript, le code source étant très similaire au code cible, tandis que dans le cas de Dart avec son code cible interminable, on peut se poser la question de son lien avec JavaScript.
9-4. Portabilité
Les trois langages permettent la conversion (ou transcompilation)
en JavaScript et donc l'accès en théorie à tous les navigateurs du
marché.
Cependant, pour bénéficier pleinement des performances promises par Dart, il est nécessaire que le navigateur dispose d'une machine virtuelle DartVM, ce qui n'est le cas actuellement que pour Chrome, évidemment. Dans la mesure où il est peu probable que Microsoft et Apple implémentent une DartVM dans Internet Explorer et dans Safari, il est raisonnable de considérer que ce qui est souvent vendu comme l'avantage décisif de Dart, ne soit finalement réservé qu'à une fraction des navigateurs. Par conséquent, Dart, à terme, devrait vraisemblablement rester marginal. Un peu comme Google Web Toolkit (2006) dont on retrouve beaucoup de caractéristiques avec Dart, et qui n'a pas vraiment eu de succès comme on peut le constater aujourd'hui.
C'est pourquoi JavaScript, en tant que langage natif de tous les navigateurs, devrait rester le seul standard pendant encore de nombreuses années.
Et l'approche de TypeScript se voulant la plus respectueuse des normes de JavaScript a de grandes chances d'être la bonne.
Cependant, pour bénéficier pleinement des performances promises par Dart, il est nécessaire que le navigateur dispose d'une machine virtuelle DartVM, ce qui n'est le cas actuellement que pour Chrome, évidemment. Dans la mesure où il est peu probable que Microsoft et Apple implémentent une DartVM dans Internet Explorer et dans Safari, il est raisonnable de considérer que ce qui est souvent vendu comme l'avantage décisif de Dart, ne soit finalement réservé qu'à une fraction des navigateurs. Par conséquent, Dart, à terme, devrait vraisemblablement rester marginal. Un peu comme Google Web Toolkit (2006) dont on retrouve beaucoup de caractéristiques avec Dart, et qui n'a pas vraiment eu de succès comme on peut le constater aujourd'hui.
C'est pourquoi JavaScript, en tant que langage natif de tous les navigateurs, devrait rester le seul standard pendant encore de nombreuses années.
Et l'approche de TypeScript se voulant la plus respectueuse des normes de JavaScript a de grandes chances d'être la bonne.
9-5. Popularité
Bien que les classements de popularité soient toujours sujets à
caution, et ne mentionnons même pas l'indice très douteux de Tiobe,
c'est souvent sur ce point que se décide l'adoption d'un langage, ce
suivisme entraînant un effet boule de neige dont chacun est libre de
penser ce qu'il voudra. Mais c'est un fait et cela a son importance.
Si nous nous basons sur la plate-forme d'hébergement de codes source GitHub qui est très prisée des développeurs Web comme l'indique la position dominante de JavaScript sur les autres langages, nous devrions avoir une tendance objective relativement proche des usages dans ce domaine.
Évolution
(1)
annuelle (d'octobre à septembre) de la création de repositories sur GitHub
On peut constater que la croissance de Dart (9 %) reste assez stable et en deçà de ses concurrents, y compris JavaScript lui-même (32 %). CoffeeScript continue quant à lui de connaître une belle dynamique avec une croissance des créations de +60 %. TypeScript qui comptabilisait en 2012-2013 moins de créations de repositories que Dart, vient de le dépasser en 2013-2014 avec un nombre de créations deux fois plus fort et une croissance annuelle qui explose à +205 %.
Ceci est un indicateur laissant à penser que TypeScript a un grand potentiel d'adoption parmi la communauté des développeurs Web malgré sa jeunesse. On peut signaler à titre d'exemple que le framework graphique babylon.js a annoncé récemment la migration de son code de JavaScript vers TypeScript. Gageons qu'avec la récente mise à disposition d'une version de production et donc stable du compilateur TypeScript, d'autres migrations d'ampleur vers ce langage voient le jour dans les mois qui viennent.
Si nous nous basons sur la plate-forme d'hébergement de codes source GitHub qui est très prisée des développeurs Web comme l'indique la position dominante de JavaScript sur les autres langages, nous devrions avoir une tendance objective relativement proche des usages dans ce domaine.
Langage | 2012-2013 | 2013-2014 | +/- |
JavaScript | 531 482 | 702 596 | 32 % |
CoffeeScript | 26 362 | 42 094 | 60 % |
Dart | 3 120 | 3 393 | 9 % |
TypeScript | 2 150 | 6 558 | 205 % |
On peut constater que la croissance de Dart (9 %) reste assez stable et en deçà de ses concurrents, y compris JavaScript lui-même (32 %). CoffeeScript continue quant à lui de connaître une belle dynamique avec une croissance des créations de +60 %. TypeScript qui comptabilisait en 2012-2013 moins de créations de repositories que Dart, vient de le dépasser en 2013-2014 avec un nombre de créations deux fois plus fort et une croissance annuelle qui explose à +205 %.
Ceci est un indicateur laissant à penser que TypeScript a un grand potentiel d'adoption parmi la communauté des développeurs Web malgré sa jeunesse. On peut signaler à titre d'exemple que le framework graphique babylon.js a annoncé récemment la migration de son code de JavaScript vers TypeScript. Gageons qu'avec la récente mise à disposition d'une version de production et donc stable du compilateur TypeScript, d'autres migrations d'ampleur vers ce langage voient le jour dans les mois qui viennent.
9-6. Récapitulatif
CoffeeScript | Dart | TypeScript | |
Maturité | 5 ans | 4 ans | 3 ans |
Code source | Open source | Open source | Open source |
Correspondance | Moyenne | Faible | Forte |
Portabilité | JavaScript | JavaScript sans DartVM | JavaScript |
Popularité | Restreinte, forte croissance |
Confidentielle, faible croissance |
Confidentielle, très forte croissance |
10. Conclusion
Cette présentation est évidemment loin d'être complète. Des
mécanismes comme les mixins n'ont pas été abordés tout comme les
possibilités offertes avec les fonctions concernant les paramètres et la
surcharge. Pour se familiariser avec TypeScript, il peut être utile
d'utiliser la page de test afin de voir instantanément la conversion d'un code TypeScript en un code JavaScript. Sinon, le guide d'utilisation et la spécification, malheureusement ni l'un ni l'autre n'étant traduit en français, restent indispensables pour approfondir le sujet.
En dépit de sa courte existence, TypeScript est un langage en pleine croissance tant sur le plan de ses spécifications que sur le plan de sa popularité. Il n'est pas parfait du fait de sa volonté de coller au plus près des normes de JavaScript, mais l'évolution de ces normes pour enrichir la syntaxe de JavaScript ainsi que des approches parallèles pour améliorer les performances comme asm.js permettent de penser que TypeScript pourrait à terme au mieux devenir lui-même un standard, au pire, inspirer les futures normes ECMAScript.
Toute proportion gardée, c'est une démarche similaire qu'avait eue à son époque Bjarne Stroustrup en concevant le C++ en tant que sur-ensemble du langage C. Et le succès jamais démenti du C++ depuis plusieurs décennies laisse à penser que TypeScript pourrait suivre le même chemin et devenir une sorte de JavaScript++.
En dépit de sa courte existence, TypeScript est un langage en pleine croissance tant sur le plan de ses spécifications que sur le plan de sa popularité. Il n'est pas parfait du fait de sa volonté de coller au plus près des normes de JavaScript, mais l'évolution de ces normes pour enrichir la syntaxe de JavaScript ainsi que des approches parallèles pour améliorer les performances comme asm.js permettent de penser que TypeScript pourrait à terme au mieux devenir lui-même un standard, au pire, inspirer les futures normes ECMAScript.
Toute proportion gardée, c'est une démarche similaire qu'avait eue à son époque Bjarne Stroustrup en concevant le C++ en tant que sur-ensemble du langage C. Et le succès jamais démenti du C++ depuis plusieurs décennies laisse à penser que TypeScript pourrait suivre le même chemin et devenir une sorte de JavaScript++.
11. Annexe : conversion en JavaScript
Les trois codes source proviennent du compte GitHub darthapo. Les codes cibles ont été réactualisés avec les derniers compilateurs en date.
11-1. CoffeeScript 1.8.0
Code source CoffeeScript
Sélectionnez
class
Simple
constructor
:
(
@name =
"
default
"
) -
>
greet
:
(
who) -
>
"
Greetings
#{
who
},
I'm
#{
@name
}!
"
@main
:
-
>
s=
new
Simple "
Flynn
"
console.
log s.
greet "
Program
"
Simple.
main
(
);
Code cible JavaScript
Sélectionnez
(
function
(
) {
var Simple;
Simple =
(
function
(
) {
function Simple
(
name
) {
this.
name
=
name
!
=
null ?
name
:
"
default
"
;
}
Simple.
prototype.
greet =
function
(
who) {
return "
Greetings
"
+
who +
"
,
I'm
"
+
this.
name
+
"
!
"
;
}
;
Simple.
main =
function
(
) {
var s;
s =
new Simple
(
"
Flynn
"
);
return console.log
(
s.greet
(
"
Program
"
));
}
;
return Simple;
}
)(
);
Simple.main
(
);
}
).call
(
this);
11-2. Dart 1.7.2
Code source Dart
Sélectionnez
class
Simple {
String
name;
Simple
(
this
.
name);
greet
(
who) =
>
"
Greetings
$who,
I'm
$name!
"
;
}
main
(
) {
var
s=
new
Simple
(
'
Flyn
'
);
print
(
s.
greet
(
'
Program
'
));
}
11-3. TypeScript 1.1
Code source TypeScript
Sélectionnez
class
Simple {
constructor
(
public
name
:
string
) {
}
greet
(
who
:
string
) {
return
"
Greetings
"
+
who +
"
,
I'm
"
+
this
.
name +
"
!
"
;
}
static
main
(
) {
var
s =
new
Simple
(
'
Flynn
'
);
console.
log
(
s.
greet
(
"
Program
"
));
}
}
Simple.
main
(
)
Code cible JavaScript
Sélectionnez
var Simple =
(
function
(
) {
function Simple
(
name
) {
this.
name
=
name
;
}
Simple.
prototype.
greet =
function
(
who) {
return "
Greetings
"
+
who +
"
,
I'm
"
+
this.
name
+
"
!
"
;
}
;
Simple.
main =
function
(
) {
var s =
new Simple
(
'
Flynn
'
);
console.log
(
s.greet
(
"
Program
"
));
}
;
return Simple;
}
)(
);
Simple.main
(
);
De la téléphonie IP très facilement avec Asterisk
Publié dans
VOip
|
mardi 13 février 2018|
ali
De la téléphonie IP très facilement avec Asterisk
Je vous propose en ce début d’année un tuto assez simple sur Asterisk. Si vous ne le connaissez pas, c’est un logiciel libre qui permet de faire de la téléphonie par IP, c’est assez sympa à faire !
Le tutorial a été réalisé sur une Debian 7.3 64bits mais peut être appliqué sur d’autres versions (un raspberry pi par exemple).
Le but à atteindre :
- Avoir un serveur de téléphonie fonctionnel, compilé à la main avec des plugins
- Pouvoir rajouter facilement des « extensions » (numéros de téléphone)
- Chaque utilisateur a une boite vocale personnelle
- Les appels groupés en conférence sont possibles
Les appels pourront même être passés depuis un iPhone / Android !
Je vous avoue qu’Asterisk et moi ça n’a jamais vraiment été une grande histoire d’amour, néanmoins je pense avoir réussi à le configurer proprement et à avoir une configuration de base qui peut servir à d’autres projets plus élaborés.
Je vous avoue qu’Asterisk et moi ça n’a jamais vraiment été une grande histoire d’amour, néanmoins je pense avoir réussi à le configurer proprement et à avoir une configuration de base qui peut servir à d’autres projets plus élaborés.
C’est parti !
Configuration réseau (à adapter selon votre topologie)
ATTENTION : si vous copiez-collez les lignes de ce tuto, vérifiez bien qu’elles soient complètes et correctes. Notamment les guillemets et tirets qui ne sont pas pareil sur cette page que dans votre console linux
nano /etc/network/interfaces
# The primary network interface
allow-hotplug eth0
iface eth0 inet static
address 192.168.1.150
netmask 255.255.255.0
gateway 192.168.1.1
Un petit ifdown eth0 et ifup eth0 pour relancer tout ça
Compilation d’asterisk
C’est ce qui va prendre le plus de temps !
Je vous invite à copier-coller ces commandes :
Je vous invite à copier-coller ces commandes :
root@asterisk:~# apt-get update && apt-get upgrade
root@asterisk:~# apt-get -f -y install build-essential linux-headers-$(uname -r) libxml2-dev libncurses5-dev libgtk2.0-dev libnewt0.52 libnewt-dev libssl-dev libsqlite3-dev
root@asterisk:~# cd /usr/src/
root@asterisk:/usr/src# wget http://downloads.asterisk.org/pub/telephony/dahdi-linux-complete/dahdi-linux-complete-current.tar.gz
root@asterisk:/usr/src# wget http://downloads.asterisk.org/pub/telephony/libpri/libpri-1.4-current.tar.gz
root@asterisk:/usr/src# wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-11-current.tar.gz
root@asterisk:/usr/src# tar xvzf dahdi-linux-complete*
root@asterisk:/usr/src# tar xvzf libpri*
root@asterisk:/usr/src# tar xvzf asterisk*
root@asterisk:/usr/src# cd /usr/src/dahdi-linux*
root@asterisk:/usr/src/dahdi # make && make install && make config
DAHDI has been configured ! –> C’est bon !
root@asterisk:# cd /usr/src/libpri*
root@asterisk:/usr/src/libpri-1.4.14# make && make install
root@asterisk:# cd /usr/src/asterisk*
root@asterisk:/usr/src/asterisk-11.7.0# ./configure
root@asterisk:/usr/src/asterisk-11.7.0# make && make menuselect && make install && make samples && make config
Ici, il faut choisir Extra Sound Packages –> CORE_SOUNDS_FR ainsi que Application –> App_meetme
Et voilà votre asterisk installé ! Vous pouvez le démarrer avec la commande :
root@asterisk:# /etc/init.d/asterisk start
Configuration d’asterisk
Allez dans /etc/asterisk. On devra y éditer au moins 3 fichiers :
- sip.conf : configuration globale du serveur VoIP avec les utilisateurs
- extensions.conf : c’est là où nous allons écrire les « numéros de téléphones » de nos clients mais aussi ceux pour la messagerie vocale, conférence, etc
- voicemail.conf : configuration de la messagerie vocale.
- iax.conf : permet de relier 2 asterisk ensemble mais ne sera pas abordé dans ce tuto.
SIP.CONF
(vous pouvez effacer celui par défaut et insérer ces lignes) :
Plusieurs sections dans ce fichier :
[general] regroupe les paramètres généraux comme le port d’exécution, le contexte, langue, etc.
[XXX] : ce sont les extensions, voyez ça comme les numéros de téléphone. Ils doivent avoir un mot de passe, un contexte et un type. Ici nous allons créer les extensions 101 et 102
Plusieurs sections dans ce fichier :
[general] regroupe les paramètres généraux comme le port d’exécution, le contexte, langue, etc.
[XXX] : ce sont les extensions, voyez ça comme les numéros de téléphone. Ils doivent avoir un mot de passe, un contexte et un type. Ici nous allons créer les extensions 101 et 102
[general]context=local ;Contexte par defaut
bindport=5060 ;UDP standard
bindaddr=0.0.0.0 ;bind access to all
srvlookup=yes ;activer les lookup DNS des appels
language=fr ;MSG vocaux en FR[101] ;Login SIPsecret=azerty ;Mot de passe
callerid= »Franky » <101> ;Affichage lors de l appel
context=local ;appels geres dans extension local
mailbox=101@default ;compte de msg vocale cfr voicemail.conf
type=friend ;allow in et out
host=dynamic ;adresse ip du client
nat=yes ;utiliser derriere du NAT[102]secret=azerty
callerid= »Kiki » <102>
context=local
type=friend
host=dynamic
nat=yes
mailbox=102@default
Extensions.conf
[default][local]
exten => _1XX, 1, Dial(SIP/${EXTEN}, 15) ; Compose 101 appelle franky etc
exten => _1XX, n, VoiceMail(${EXTEN}) ; Voicemail apres 15 secondes
exten => 90,1,VoiceMailMain(${CALLERID(num)}) ; Messagerie
exten => 300, 1, Meetme(300)
Voicemail.conf
Elle sera accessible par le numéro « 90 » (cfr fichier précédent)
[general]format=wav49|gsm|wav
attach=yes
serveremail = SRV-Asterisk@sen-tr.fr; Mail de expediteur
emailsubject=Nouveau petit message de ${VM_CIDNAME}
emailbody=\n\tBonjour ${VM_NAME},\n\n\tTu as un petit message de la part de ${VM_CIDNAME} d une duree de ${VM_DUR} datant du ${VM_D}[default]
101 = 123, Franky ; login 101, password 123
102 = 123, Kiki
Notez que vous devez mettre les noms définis dans les Caller ID de sip.conf
La gestion des conférences
Rien de plus facile, nous avons déjà configuré le numéro 300 dans les extensions. Il faut cependant sécuriser la conférence par un mot de passe !
root@asterisk:# nano /etc/asterisk/meetme.conf
On rajoute ceci en fin de fichier :
conf => 300,1234 ;numero et password
Il ne reste plus qu’à relancer le service Asterisk et à s’y connecter !
Exemple ce configuration sur iPhone :
Exemple ce configuration sur iPhone :
Il existe de nombreuses applications disponibles, comme par exemple ZoIPer sur iOS et CSipSimple sur Android. Si vous avez un téléphone sous android 2.3 ou plus, vous pouvez directement renseigner les paramètres de compte dans l’application téléphone.
Vidéos similaires
Messages populaires
-
Installation pas à pas de Nagios Trêve de blabla, entrons directement dans le vif du sujet avec l'installation d...
-
Si vous souhaitez scanner une plage d’adresse IP sur votre réseau afin de vérifier la disponibilité d’une ou plusieurs...
-
Installation de Cacti sous Debian Les systèmes informatiques d'entreprise associent une diversité de services proposés (rout...
-
C’est quoi le DFS ? I. Présentation Ce premier article a pour but d’expliquer ce qu’est le DFS, accessible dans u...
-
Qu’est-ce que le NAT ? Commençons par la signification du NAT, Network Address Translation (en Français Translation d’Adresse Réseau)...
-
Création d’une règle de pare-feu avec un Fortigate I. Présentation Après avoir découvert ce qu’est un Fortinet dans un premier ...
-
Active Directory I. L’Active Directory L’Active Directory est un annuaire LDAP pour les systèmes d’exploitation Windows, l...
-
IPerf: des exemples… Nous commençons l'année 2008 avec un billet regroupant des exemples d'utilisation d'IPerf, l'...
-
Comment exécuter un script PowerShell Dans l’article comment installer et vérifier le bon fonctionnement de PowerShell , nous av...
-
Routage RIP Définitions Avant de parler de routage RIP, il faut que j’explique qu’est-ce qu’un routeur et quel est son but. Le ...
pobular post
Fourni par Blogger.
Recent Stories
CONNECTER AVEC FACEBOOK
Sponsors
Chercher
Archives
Contactez Moi