+ Répondre à la discussion Actualité déjà publiée
  1. #1
    Rédacteur/Modérateur

    Avatar de yahiko
    Homme Profil pro
    Ninja
    Inscrit en
    juillet 2013
    Messages
    1 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ninja

    Informations forums :
    Inscription : juillet 2013
    Messages : 1 147
    Points : 6 483
    Points
    6 483
    Billets dans le blog
    43

    Par défaut ECMAScript 6 et TypeScript

    ECMAScript 6 et TypeScript


    La proximité temporelle entre la version 1.5 alpha de TypeScript (TS) annoncée récemment et la prochaine validation officielle de la norme ECMAScript 6 (ES6) tant attendue, en principe en juin est l'occasion de faire le point sur les fonctionnalités ES6 supportées par le langage de Microsoft.

    Il existe un site recensant le niveau de compatibilité avec la norme ES6 des différents navigateurs et transpileurs JavaScript.

    Bien entendu, la version 1.5 alpha de TS y est référencée, dans la catégorie compilateurs/polyfills.

    On constate qu'en terme de couverture brute, TS est à 25% à comparer par exemple au 75% de Babel (anciennement 6to5). On est encore loin du compte certes mais contrairement à Babel ou à Traceur qui se veulent de purs transpileurs avec justement pour unique objectif de transpiler en ES5 du code ES6, TS se veut être plus qu'un transpileur, mais bien un langage à part entière avec des contraintes qui lui sont propres.

    On constate d'ailleurs si on considère un langage qui comme TS n'est pas uniquement un transpileur, que le taux de couverture brute de Clojure, de 29%, est similaire à celui de TS.

    Il faut aussi considérer ce taux de couverture de 25% avec quelques précautions dans la mesure où toutes les fonctionnalités ne sont pas d'égale importance en pratique.

    Toujours est-il que ce tableau classe les différentes fonctionnalités de la norme ES6 en trois catégories : utile, significative et emblématique (landmark). Focalisons-nous sur cette dernière catégorie, une revue exhaustive étant beaucoup trop longue pour votre humble serviteur, et regardons la couverture de TS concernant ces fonctionnalités dites emblématiques (même s'il faut garder à l'esprit que cette classification reste subjective et propre à ce site).

    Syntaxe :

    Opérateur d'expansion (...) : 2/10
    L'opérateur d'expansion (spread) permet d'extraire sous la forme d'une séquence séparée par des virgules, l'ensemble des éléments d'une collection.

    TS 1.5 supporte le cas le plus évident, celui avec un tableau.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var x = Math.max(...[1, 2, 3]);
    est équivalent à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var x = Math.max(1, 2, 3);
    TS 1.5 ne prend pas en charge les autres cas moins naturels (et moins fréquents) prévus par la norme concernant les chaînes de caractères. Il n'est donc pas possible d'utiliser l'opérateur comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var x = Math.max(..."123"]);
    TS 1.5 ne prend pas non plus en charge le cas plus général des objets itérables génériques définis à l'aide de la fonction global.__createIterableObject().

    Extensions des objets littéralement définis : 5/6
    Lorsqu'on définissait explicitement un objet {...} , ses propriétés ne pouvaient avoir qu'un nom littéral, c'est-à-dire être un symbole terminal dans le jargon de la théorie des langages. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    var obj = { a: 1, b: 2 };
    obj.a === 1;
    obj.b === 2;
    Les propriétés a et b de l'objet obj ainsi défini sont désignées explicitement par un identificateur. Or, il était également possible de définir les propriétés d'un objet avec des noms calculés, via une approche dynamique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    var x = 'a';
    var y = 'b';
    var obj = {};
    obj[x] = 1;
    obj[y] = 2;
    obj.a === 1;
    obj.b === 2;
    Avec la norme ES6, cette frontière disparaît et il est possible de définir explicitement un objet avec des noms de propriétés calculées :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    var x = 'a';
    var y = 'b';
    var obj = { [x]: 1, [y]: 2 };
    obj.a === 1;
    obj.b === 2;
    TS 1.5 prend en charge cette nouvelle fonctionnalité, à l'exception des accesseurs get et set qui eux doivent encore être nommés avec un littéral.

    Boucle for..of : 2/7
    Cette nouvelle construction de boucle permet d'itérer sur une collection de façon plus pratique qu'avec la construction for..in puisque la variable de contrôle n'est plus la clé de l'élément itéré mais bien sa valeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    var arr = ['Hello ', 'world! '];
    var sentence = '';
    for (var item of arr) {
        sentence += item;
    }
    sentence === 'Hello world! ';
    TS 1.5 permet d'utiliser cette nouvelle construction pour itérer sur des tableaux et des chaînes de caractères.

    Cependant, cette construction en TS 1.5 ne prend pas encore en charge l'Unicode étendu (plan astral) ni les objets itérables génériques.

    Interpolation de chaînes : 2/2
    L'interpolation de chaînes de caractères permet d'une part de fractionner les chaînes littérales sur plusieurs lignes et permet d'autre part d'exprimer certaines parties d'une chaîne littérale par une expression qui sera évaluée à l'exécution. Cela permet d'améliorer la lisibilité du code en limitant l'usage massif de concaténations, notamment lorsqu'il s'agit de construire du code HTML à la volée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    var a = "ba", b = "QUX";
    var str = `foo bar
    ${a + "z"} ${b.toLowerCase()}`
    str === "foo bar\nbaz qux";
    TS 1.5 supporte pleinement cette nouvelle fonctionnalité.

    Déstructuration : 20/30
    L'affectation par décomposition, ou plus littéralement la déstructuration, permet d'éviter l'usage de certaines variables intermédiaires et rend ainsi le code plus lisible lorsqu'il s'agit de manipuler des n-uplets (ou tuples) soit sous la forme de tableaux ou sous la forme de chaînes de caractères.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    var a, b;
    [a, b] = [1, 2];
    a === 1 && b === 2;
    [a, b] = [b, a];
    a === 2 && b === 1;
    TS 1.5 supporte cette fonctionnalité pour l'essentiel, à part les cas liés aux objets itérables génériques, au passage en paramètres du constructeur de Function(), et quelques bugs probablement en cours de correction.

    Fonctions :

    Fonctions anonymes fléchées : 8/11
    La notation fléchée permet de simplifier l'écriture des fonctions anonymes dans la mesure où sa notation est plus concise et où elle permet la conservation du contexte this de la fonction de portée lexicale immédiatement supérieure, ce qui évite l'utilisation intempestive de variables intermédiaires _this ou that ou bien l'abus de bind(). Cette notation fléchée permet aussi la conservation du contexte arguments de la fonction de portée lexicale immédiatement supérieure.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function AlertMsg1(msg) {
        this.msg = msg;
        this.timer = setTimeout(function () { alert(this.msg); }, 1000);
    }
    function AlertMsg2(msg) {
        this.msg = msg;
        this.timer = setTimeout(() => { alert(this.msg); }, 2000);
    }
    var a1 = new AlertMsg1('Hello world!'); // undefined
    var a2 = new AlertMsg2('Goodbye folks!'); // 'Goodbye folks!'
    TS a supporté cette fonctionnalité très tôt et on la retrouve évidemment dans la version 1.5. Seuls quelques manquements à la norme subsistent comme l'absence de la conservation du contexte arguments ou le fait que cette fonction anonyme fléchée possède anormalement une propriété prototype.

    Classes : 14/23
    Les classes sont l'un des piliers de la programmation orientée objet au sens classique du terme.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class C {
        constructor(a, b) {
            this.a = a;
            this.b = b;
        }
    }
    c = new C(1, 2);
    c.a === 1;
    c.b === 2;
    TS a intégré les classes depuis ses débuts, cela a même été une de ses motivations premières, dans la mesure où la notion de classe s'inscrit dans la notion plus générale des types. La version 1.5 de TS a encore quelques lacunes par rapport à la norme ES6 comme la possibilité d'imbriquer des classes ou la notion de classe anonyme.

    Générateurs : 0/21
    Les générateurs sont une possibilité offerte par la norme ES6 de faciliter le multitâche coopératif à l'aide de fonctions dites génératrices et du mot-clé yield.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function* coop(){
        var index = 0;
        while (index <= 2)
            yield index++;
    };
     
    var iterator = coop();
    iterator.next().value === 0;
    iterator.next().value === 1;
    iterator.next().value === 2;
    iterator.next().value === undefined;
    TS 1.5 n'implémente pas encore cette fonctionnalité. Elle est prévue dans la version suivante, la 1.6.

    Prédéfinitions :

    Tableaux typés : 0/40
    Les tableaux typés sont une fonctionnalité de la norme ES6 permettant des optimisations lorsqu'il s'agit de manipuler de grandes quantités de données, souvent de même nature ou de même format, prédéterminé à l'avance.

    TS 1.5 ne supporte cette fonctionnalité qu'en ciblant du code ES6. Il ne peut pas transpiler cette construction en code ES5 pour le moment.

    Proxy : 0/20
    Les proxy généralisent le concept d'accesseur en permettant de personnaliser le comportement d'un objet lors des accès à ses propriétés ou lors de son instanciation via l'opérateur new.

    TS 1.5 ne supporte cette fonctionnalité qu'en ciblant du code ES6. Il ne peut pas transpiler cette construction en code ES5 pour le moment.

    Promesses : 0/3
    Les promesses sont un design pattern assez commode pour simplifier la programmation asynchrone, surtout lorsqu'il s'agit de traiter non pas un événement mais une collection d'événements.

    TS 1.5 ne supporte cette fonctionnalité qu'en ciblant du code ES6. Il ne peut pas transpiler cette construction en code ES5 pour le moment. Les promesses seront à l'ordre du jour dans la version 1.6 en parallèle des constructions async/await.

    Conclusion

    Ce petit tour d'horizon de la couverture ES6 de TS n'est évidemment pas exhaustif puisque les fonctionnalités classées en utiles et significatives n'ont pas été abordées.

    Il faut de plus garder à l'esprit que TS n'est pas un transpileur pur mais un langage à part entière qui en plus des fonctionnalités ES6 qu'il intégrera à terme, propose d'autres concepts et notamment le typage (annotations de type, unions de types, interfaces, ...).

    Cela n'a donc pas vraiment de sens d'opposer ES6 à TS comme il est parfois possible de lire en se promenant sur la toile. ES6 ne va pas rendre TS obsolète, tout comme TS n'a pas vocation à remplacer ES6.

    Enfin, concernant la couverture de la norme ES6 par TS, même si toutes les fonctionnalités peuvent ne pas être transpilées en fin de compte en ES5, la mise à la norme des navigateurs rendra ce besoin moins crucial au fur et à mesure que le temps s'écoulera. Il ne faut donc pas faire du tableau de couverture fonctionnelle le critère absolu de l'alignement de TypeScript avec la norme ES6.
    Tutoriels et FAQ TypeScript

  2. #2
    Membre confirmé
    Avatar de Paleo
    Homme Profil pro
    Développeur Web
    Inscrit en
    septembre 2013
    Messages
    211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : septembre 2013
    Messages : 211
    Points : 588
    Points
    588

    Par défaut

    Jusqu'ici l'équipe de TypeScript s'est strictement tenue à un principe : le code ES3/5 généré ne doit dépendre d'aucune bibliothèque JS à l'exécution.

    Pour une VM ES3/5, cela élimine toutes les nouvelles API de ES6 qui nécessitent des polyfills, dont l'objet Symbol (et donc les itérateurs), les Map, Set et autres tableaux typés, les proxies, promesses, l'API Reflect pour ne citer que les plus attendues. Ce sont des fonctionnalités utilisables en TypeScript mais le format du code généré doit alors être ES6.

    Certaines API peuvent être utilisées en TypeScript sur une VM ES3/5 grâce à des polyfills autonomes : les promesses, les Map, Set, Reflect, et un bon nombre d'extensions dans les API existantes. Par exemple avec es6-shim. Mais, par design, les fonctionnalités qui nécessitent une collaboration entre le transpileur et le polyfill ne sont pas accessibles en TS : en particulier, les itérateurs.

    Concernant les générateurs prévus dans TypeScript 1.6, je me demande bien comment ils vont faire. Babel utilise sa lib JS.

    Citation Envoyé par yahiko Voir le message
    ES6 ne va pas rendre TS obsolète
    Contrairement à Babel, ex 6to5. Mais ses développeurs ont pris les devants en renommant leur projet. Babel est désormais le transpileur qui implémente les futures normes au niveau 2 (draft).

  3. #3
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    novembre 2012
    Messages
    3 196
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : novembre 2012
    Messages : 3 196
    Points : 9 314
    Points
    9 314

    Par défaut

    Je me demande si ce ne serait pas plus simple pour eux de transpiler TypeScript en ES6 puis d'utiliser Babel à la volée pour transpiler en ES5. On ne capitalise pas beaucoup sur le travail fait par ces outils open-source.
    One Web to rule them all

  4. #4
    Membre confirmé
    Avatar de Paleo
    Homme Profil pro
    Développeur Web
    Inscrit en
    septembre 2013
    Messages
    211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : septembre 2013
    Messages : 211
    Points : 588
    Points
    588

    Par défaut

    Citation Envoyé par SylvainPV Voir le message
    Je me demande si ce ne serait pas plus simple pour eux de transpiler TypeScript en ES6 puis d'utiliser Babel à la volée pour transpiler en ES5. On ne capitalise pas beaucoup sur le travail fait par ces outils open-source.
    Tout d'abord TypeScript compile des classes ES6 depuis 2012, bien avant Babel/6to5. Dans le cadre d'une exécution sur une VM ES3/5, il ne faut pas se voiler la face, Babel et TypeScript sont deux outils partiellement concurrents.

    Et puis il y a des cas où TypeScript est par design plus performant que Babel. Prenons ce code en ES6:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    let arr = ['a', 'b', 'c'];
    for (let item of arr) {
      console.log(item);
    }
    TypeScript 1.5-aplha le transpile ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    var arr = ['a', 'b', 'c'];
    for (var _i = 0; _i < arr.length; _i++) {
        var item_1 = arr[_i];
        console.log(item_1);
    }
    Mais voici ce que donne la version Babel (sur le REPL):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    'use strict';
     
    var arr = ['a', 'b', 'c'];
    var _iteratorNormalCompletion = true;
    var _didIteratorError = false;
    var _iteratorError = undefined;
     
    try {
      for (var _iterator = arr[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
        var item = _step.value;
     
        console.log(item);
      }
    } catch (err) {
      _didIteratorError = true;
      _iteratorError = err;
    } finally {
      try {
        if (!_iteratorNormalCompletion && _iterator['return']) {
          _iterator['return']();
        }
      } finally {
        if (_didIteratorError) {
          throw _iteratorError;
        }
      }
    }
    Pourquoi cette horreur sur Babel ? À cause des itérateurs. En effet, Babel ne dispose pas d'informations sur le type de la variable "arr". Par conséquent il fait appel à son polyfill de "Symbol" systématiquement, alors que pour itérer sur un simple tableau c'est inutile.

    Peut-être qu'un jour TypeScript fournira un polyfill pour Symbol mais il saura de toute manière toujours générer du code élégant pour les tableaux dont il connait le typage.

  5. #5
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    novembre 2012
    Messages
    3 196
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : novembre 2012
    Messages : 3 196
    Points : 9 314
    Points
    9 314

    Par défaut

    Ok je comprends mieux. Mais Babel ne peut-il pas reconnaître les Arrays par inférence, puisqu'il a tout le code source à disposition ? J'ai l'impression que TypeScript s'est concentré dès le départ sur les performances tandis que Babel voulait le plus de fonctionnalités ES6 possibles.
    One Web to rule them all

  6. #6
    Rédacteur/Modérateur

    Avatar de yahiko
    Homme Profil pro
    Ninja
    Inscrit en
    juillet 2013
    Messages
    1 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ninja

    Informations forums :
    Inscription : juillet 2013
    Messages : 1 147
    Points : 6 483
    Points
    6 483
    Billets dans le blog
    43

    Par défaut

    Pour Babel, je ne sais pas exactement, même si oui je pense qu'il a priorisé sur les fonctionnalités ES6 avant tout.
    Pour TypeScript, je dirais qu'avant les performances, il s'attache à restituer du code JavaScript aussi proche que possible de l'original TypeScript.
    Tutoriels et FAQ TypeScript

  7. #7
    Membre confirmé
    Avatar de Paleo
    Homme Profil pro
    Développeur Web
    Inscrit en
    septembre 2013
    Messages
    211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : septembre 2013
    Messages : 211
    Points : 588
    Points
    588

    Par défaut

    La performance par l'élégance est la bonne manière de faire.

    Babel est un projet plus léger que TypeScript. Il n'implémente pas d'inférence de type, il ne génère aucune erreur, par exemple, si l'on remplace l'initialisation de arr par : "let arr = {};". Pourtant les objets ne sont pas itérables. Mais de toute manière il suffirait que la variable "arr" soit un paramètre passé à une fonction pour empêcher l'inférence en syntaxe ES6 pure.

    L'inférence à la manière de TypeScript parait naturelle et intuitive, mais je ne pense pas que son implémentation soit une petite affaire. En fait il est assez possible que 80% du code du compilateur TS soit destiné au parseur et à la représentation interne du code analysé, et que les sorties prennent les 20% restant : la génération des codes ECMAScript plus TS Server (l'analyse syntaxique prête à emploi pour les éditeurs). Donc il serait dommage que TypeScript se prive de terminer le travail. Sans parler des soucis de performance du compilateur lui-même : s'il fallait ajouter un deuxième niveau de transpilation, à l'usage, ça ralentirait.

  8. #8
    Membre régulier
    Homme Profil pro
    Développeur Java / JEE / JavaScript
    Inscrit en
    juillet 2012
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Java / JEE / JavaScript
    Secteur : Service public

    Informations forums :
    Inscription : juillet 2012
    Messages : 32
    Points : 71
    Points
    71

    Par défaut

    Citation Envoyé par yahiko Voir le message
    ES6 ne va pas rendre TS obsolète
    Par contre quand Javascript implémentera ES6, je ne verrais plus d'intérêt à Typescript ou même Dart

  9. #9
    Rédacteur/Modérateur

    Avatar de yahiko
    Homme Profil pro
    Ninja
    Inscrit en
    juillet 2013
    Messages
    1 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ninja

    Informations forums :
    Inscription : juillet 2013
    Messages : 1 147
    Points : 6 483
    Points
    6 483
    Billets dans le blog
    43

    Par défaut

    J'ai du louper quelque chose dans mon explication alors.
    TypeScript apporte le typage statique, d'où son nom, et permet ainsi d'écrire des applications Web de grandes envergures plus facilement et de façon plus fiable qu'avec du JavaScript pur, y compris ES6.
    Tutoriels et FAQ TypeScript

Discussions similaires

  1. Client Objet Model ECMAScript et autorisation réfusée
    Par cyril.legret dans le forum Développement Sharepoint
    Réponses: 3
    Dernier message: 17/06/2011, 11h00
  2. Enorme ! Bero's EcmaScript Engine
    Par Paul TOTH dans le forum Composants VCL
    Réponses: 2
    Dernier message: 18/12/2010, 18h36
  3. jLang : extension du ECMAScript
    Par Spirit 203 dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 03/11/2010, 16h55
  4. [Ecmascript] application externe
    Par ebaynaud dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 02/03/2006, 13h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo