IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

TypeScript Discussion :

Microsoft annonce la disponibilité de TypeScript 5.5 Beta


Sujet :

TypeScript

  1. #1
    Communiqués de presse

    Femme Profil pro
    Traductrice Technique
    Inscrit en
    Juin 2023
    Messages
    1 215
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Traductrice Technique

    Informations forums :
    Inscription : Juin 2023
    Messages : 1 215
    Points : 84 937
    Points
    84 937
    Par défaut Microsoft annonce la disponibilité de TypeScript 5.5 Beta
    Microsoft annonce la disponibilité de TypeScript 5.5 Beta, cette version apporte les prédicats de type inférés et réduit le flux de controle pour les accès indexés constants.

    Microsoft annonce la disponibilité de TypeScript 5.5 Beta. Parmi les nouveautés : Prédicats de type inférés, réduction du flux de contrôle pour les accès indexés constants, importations de types dans JSDoc, vérification de la syntaxe des expressions régulières, et plus encore.

    Nom : 1.jpg
Affichages : 48881
Taille : 10,6 Ko

    Prédicats de type inférés

    L'analyse du flux de contrôle de TypeScript fait un excellent travail de suivi de la façon dont le type d'une variable change au fur et à mesure qu'elle se déplace dans votre code :

    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
    interface Bird {
        commonName: string;
        scientificName: string;
        sing(): void;
    }
     
    // Maps country names -> national bird.
    // Not all nations have official birds (looking at you, Canada!)
    declare const nationalBirds: Map<string, Bird>;
     
    function makeNationalBirdCall(country: string) {
      const bird = nationalBirds.get(country);  // bird has a declared type of Bird | undefined
      if (bird) {
        bird.sing();  // bird has type Bird inside the if statement
      } else {
        // bird has type undefined here.
      }
    }
    En vous obligeant à gérer les cas indéfinis, TypeScript vous pousse à écrire un code plus robuste.

    Dans le passé, ce type de raffinement de type était plus difficile à appliquer aux tableaux. Cela aurait été une erreur dans toutes les versions précédentes de TypeScript :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function makeBirdCalls(countries: string[]) {
      // birds: (Bird | undefined)[]
      const birds = countries
        .map(country => nationalBirds.get(country))
        .filter(bird => bird !== undefined);
     
      for (const bird of birds) {
        bird.sing();  // error: 'bird' is possibly 'undefined'.
      }
    }
    Ce code est parfaitement correct : ils ont filtré toutes les valeurs indéfinies de la liste. Mais TypeScript n'a pas été en mesure de suivre le mouvement.

    Avec TypeScript 5.5, le vérificateur de type n'a rien à redire à ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function makeBirdCalls(countries: string[]) {
      // birds: Bird[]
      const birds = countries
        .map(country => nationalBirds.get(country))
        .filter(bird => bird !== undefined);
     
      for (const bird of birds) {
        bird.sing();  // ok!
      }
    }
    Notez le type plus précis pour les birds.

    Cela fonctionne parce que TypeScript déduit maintenant un prédicat de type pour la fonction de filtrage. Vous pouvez voir plus clairement ce qui se passe en la transformant en une fonction indépendante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // function isBirdReal(bird: Bird | undefined): bird is Bird
    function isBirdReal(bird: Bird | undefined) {
      return bird !== undefined;
    }
    bird is Bird est le prédicat de type. Cela signifie que si la fonction renvoie true, il s'agit d'un bird (si la fonction renvoie false, il s'agit d'un indéfini). Les déclarations de type pour Array.prototype.filter connaissent les prédicats de type, de sorte que le résultat net est que vous obtenez un type plus précis et que le code passe le vérificateur de type.

    TypeScript déduira qu'une fonction renvoie un prédicat de type si ces conditions sont remplies :

    1. La fonction n'a pas d'annotation explicite de type de retour ou de prédicat de type.
    2. La fonction a un seul énoncé de retour et aucun retour implicite.
    3. La fonction ne modifie pas son paramètre.
    4. La fonction renvoie une expression booléenne liée à un raffinement du paramètre.


    En règle générale, tout se passe comme prévu. Voici quelques autres exemples de prédicats de types déduits :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // const isNumber: (x: unknown) => x is number
    const isNumber = (x: unknown) => typeof x === 'number';
     
    // const isNonNullish: <T>(x: T) => x is NonNullable<T>
    const isNonNullish = <T,>(x: T) => x != null;
    Auparavant, TypeScript aurait simplement déduit que ces fonctions renvoient une expression booléenne. Il déduit maintenant les signatures avec des prédicats de type comme x est un nombre ou x est NonNullable<T>.

    Les prédicats de type ont une sémantique « si et seulement si ». Si une fonction renvoie x is T, cela signifie que :

    1. Si la fonction renvoie un résultat vrai, x est de type T.
    2. Si la fonction renvoie faux, x n'est pas de type T.


    Si vous vous attendez à ce qu'un prédicat de type soit déduit mais qu'il ne l'est pas, vous risquez de vous heurter à la deuxième règle. Ce problème se pose souvent dans le cadre des vérifications de « véracité » :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function getClassroomAverage(students: string[], allScores: Map<string, number>) {
      const studentScores = students
        .map(student => allScores.get(student))
        .filter(score => !!score);
     
      return studentScores.reduce((a, b) => a + b) / studentScores.length;
      //     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      // error: Object is possibly 'undefined'.
    }
    TypeScript n'a pas déduit de prédicat de type pour score => !!score, et ce à juste titre : si ce prédicat retourne vrai, alors score est un nombre. Mais s'il renvoie false, alors score peut être soit indéfini, soit un nombre (en particulier, 0). Il s'agit d'un véritable bogue : si un étudiant a obtenu un zéro à l'examen, le fait de filtrer son score faussera la moyenne vers le haut. Moins d'élèves seront au-dessus de la moyenne et plus d'élèves seront tristes !

    Comme dans le premier exemple, il est préférable de filtrer explicitement les valeurs indéfinies :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function getClassroomAverage(students: string[], allScores: Map<string, number>) {
      const studentScores = students
        .map(student => allScores.get(student))
        .filter(score => score !== undefined);
     
      return studentScores.reduce((a, b) => a + b) / studentScores.length;  // ok!
    }
    Un contrôle de véracité déduira un prédicat de type pour les types d'objets, là où il n'y a pas d'ambiguïté. Rappelez-vous que les fonctions doivent retourner un booléen pour être candidates à un prédicat de type inféré : x => !!x peut inférer un prédicat de type, mais x => x ne le fera certainement pas.

    Les prédicats de type explicites continuent à fonctionner exactement comme avant. TypeScript ne vérifiera pas s'il déduit le même prédicat de type. Les prédicats de type explicites (« is ») ne sont pas plus sûrs qu'une assertion de type (« as »).

    Il est possible que cette fonctionnalité casse du code existant si TypeScript déduit maintenant un type plus précis que ce que vous souhaitez. Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // Previously, nums: (number | null)[]
    // Now, nums: number[]
    const nums = [1, 2, 3, null, 5].filter(x => x !== null);
     
    nums.push(null);  // ok in TS 5.4, error in TS 5.5
    La solution consiste à indiquer à TypeScript le type que vous souhaitez en utilisant une annotation de type explicite :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    const nums: (number | null)[] = [1, 2, 3, null, 5].filter(x => x !== null);
    nums.push(null);  // ok in all versions

    Réduction du flux de contrôle pour les accès indexés constants

    TypeScript est désormais capable de réduire les expressions de la forme obj[key] lorsque obj et key sont effectivement constants.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    function f1(obj: Record<string, unknown>, key: string) {
        if (typeof obj[key] === "string") {
            // Now okay, previously was error
            obj[key].toUpperCase();
        }
    }
    Dans l'exemple ci-dessus, ni obj ni key ne sont jamais mutés, donc TypeScript peut limiter le type de obj[key] à string après la vérification de typeof.


    Importations de types dans JSDoc

    Aujourd'hui, si vous voulez importer quelque chose uniquement pour vérifier le type dans un fichier JavaScript, c'est encombrant. Les développeurs JavaScript ne peuvent pas simplement importer un type nommé SomeType s'il n'est pas présent au moment de l'exécution.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // ./some-module.d.ts
    export interface SomeType {
        // ...
    }
     
    // ./index.js
    import { SomeType } from "./some-module"; //  runtime error!
     
    /**
     * @param {SomeType} myValue
     */
    function doSomething(myValue) {
        // ...
    }
    SomeType n'existera pas au moment de l'exécution, et l'importation échouera. Les développeurs peuvent à la place utiliser une importation d'espace de noms.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    import * as someModule from "./some-module";
     
    /**
     * @param {someModule.SomeType} myValue
     */
    function doSomething(myValue) {
        // ...
    }
    Mais ./some-module est toujours importé à l'exécution, ce qui n'est pas forcément souhaitable.

    Pour éviter cela, les développeurs devaient généralement utiliser des types import(...) dans les commentaires JSDoc.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    /**
     * @param {import("./some-module").SomeType} myValue
     */
    function doSomething(myValue) {
        // ...
    }
    Si vous vouliez réutiliser le même type à plusieurs endroits, vous pouviez utiliser un typedef pour éviter de répéter l'importation.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /**
     * @typedef {import("./some-module").SomeType} SomeType
     */
     
    /**
     * @param {SomeType} myValue
     */
    function doSomething(myValue) {
        // ...
    }
    Cela est utile pour les utilisations locales de SomeType, mais cela devient répétitif pour de nombreuses importations et peut être un peu verbeux.

    C'est pourquoi TypeScript prend désormais en charge une nouvelle balise de commentaire @import qui a la même syntaxe que les importations ECMAScript.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    /** @import { SomeType } from "some-module" */
     
    /**
     * @param {SomeType} myValue
     */
    function doSomething(myValue) {
        // ...
    }
    Ici, ils ont utilisé des importations nommées. Ils auraient également pu écrire l'importation comme une importation d'espace de noms.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    /** @import * as someModule from "some-module" */
     
    /**
     * @param {someModule.SomeType} myValue
     */
    function doSomething(myValue) {
        // ...
    }
    Comme il ne s'agit que de commentaires JSDoc, ils n'affectent en rien le comportement à l'exécution.


    Vérification syntaxique des expressions régulières

    Jusqu'à présent, TypeScript a généralement ignoré la plupart des expressions régulières dans le code. En effet, les expressions régulières ont techniquement une grammaire extensible et TypeScript n'a jamais fait d'effort pour compiler les expressions régulières dans les versions antérieures de JavaScript. Néanmoins, cela signifiait que de nombreux problèmes courants n'étaient pas découverts dans les expressions régulières et qu'ils se transformaient en erreurs au moment de l'exécution ou échouaient silencieusement.

    Mais TypeScript effectue désormais un contrôle syntaxique de base sur les expressions régulières !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    let myRegex = /@robot(\s+(please|immediately)))? do some task/;
    //                                            ~
    // error!
    // Unexpected ')'. Did you mean to escape it with backslash?
    Il s'agit d'un exemple simple, mais cette vérification peut permettre de détecter de nombreuses erreurs courantes. En fait, le contrôle de TypeScript va un peu plus loin que les contrôles syntaxiques. Par exemple, TypeScript peut maintenant détecter les problèmes liés à des références arrière qui n'existent pas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    let myRegex = /@typedef \{import\((.+)\)\.([a-zA-Z_]+)\} \3/u;
    //                                                        ~
    // error!
    // This backreference refers to a group that does not exist.
    // There are only 2 capturing groups in this regular expression.
    Il en va de même pour les groupes de capture nommés.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    let myRegex = /@typedef \{import\((?<importPath>.+)\)\.(?<importedEntity>[a-zA-Z_]+)\} \k<namedImport>/;
    //                                                                                        ~~~~~~~~~~~
    // error!
    // There is no capturing group named 'namedImport' in this regular expression.
    La vérification de TypeScript est désormais également consciente de l'utilisation de certaines fonctionnalités RegExp lorsque celles-ci sont plus récentes que votre version cible d'ECMAScript. Par exemple, si on utilise des groupes de capture nommés comme ci-dessus dans une cible ES5, on obtiendra une erreur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    let myRegex = /@typedef \{import\((?<importPath>.+)\)\.(?<importedEntity>[a-zA-Z_]+)\} \k<importedEntity>/;
    //                                  ~~~~~~~~~~~~         ~~~~~~~~~~~~~~~~
    // error!
    // Named capturing groups are only available when targeting 'ES2018' or later.
    Il en va de même pour certains drapeaux d'expressions régulières.

    Notez que la prise en charge des expressions régulières par TypeScript est limitée aux expressions régulières littérales. Si vous essayez d'appeler new RegExp avec une chaîne littérale, TypeScript ne vérifiera pas la chaîne fournie.


    Déclarations isolées

    Les fichiers de déclaration (alias fichiers .d.ts) décrivent la forme des bibliothèques et modules existants en TypeScript. Cette description légère comprend les signatures de type de la bibliothèque et exclut les détails d'implémentation tels que les corps des fonctions. Ils sont publiés afin que TypeScript puisse vérifier efficacement votre utilisation d'une bibliothèque sans avoir besoin d'analyser la bibliothèque elle-même. Bien qu'il soit possible d'écrire à la main des fichiers de déclaration, si vous écrivez du code typé, il est beaucoup plus sûr et plus simple de laisser TypeScript les générer automatiquement à partir des fichiers source en utilisant --declaration.

    Le compilateur TypeScript et ses API ont toujours été chargés de générer les fichiers de déclaration ; cependant, dans certains cas d'utilisation, il est préférable d'utiliser d'autres outils, ou le processus de construction traditionnel n'est pas adapté.

    • Cas d'utilisation : Outils d'émission de déclarations plus rapides

      Imaginez que vous souhaitiez créer un outil plus rapide pour générer des fichiers de déclaration, peut-être dans le cadre d'un service de publication ou d'un nouveau bundler. S'il existe un écosystème florissant d'outils ultra-rapides capables de transformer TypeScript en JavaScript, il n'en va pas de même pour la transformation de TypeScript en fichiers de déclaration. La raison en est que l'inférence de TypeScript nous permet d'écrire du code sans déclarer explicitement les types, ce qui signifie que l'émission de déclarations peut être complexe.

      Bien que cette inférence soit importante pour le développeur, cela signifie que les outils qui souhaitent générer des fichiers de déclaration devraient reproduire certaines parties du vérificateur de type, notamment l'inférence et la capacité à résoudre les spécificateurs de modules pour suivre les importations.

    • Cas d'utilisation : Déclaration parallèle Emit et vérification parallèle

      Imaginez que vous ayez une monorepo contenant de nombreux projets et un processeur multicœur qui souhaiterait vous aider à vérifier votre code plus rapidement. Ne serait-ce pas génial si nous pouvions vérifier tous ces projets en même temps en exécutant chaque projet sur un cœur différent ?

      Malheureusement, on n'a pas la liberté de faire tout le travail en parallèle. La raison est qu'on doit construire ces projets dans l'ordre des dépendances, parce que chaque projet vérifie les fichiers de déclaration de ses dépendances. On doit donc construire la dépendance en premier pour générer les fichiers de déclaration. La fonction de références de projet de TypeScript fonctionne de la même manière, en construisant l'ensemble des projets dans l'ordre de dépendance « topologique ».

      Nom : 1.jpg
Affichages : 4363
Taille : 22,3 Ko

      Comment pourrait-on améliorer cela ? Eh bien, si un outil rapide pouvait générer tous ces fichiers de déclaration pour le noyau en parallèle, TypeScript pourrait immédiatement suivre en vérifiant le type du noyau, du frontend et du backend également en parallèle.

    • Solution : Types explicites !

      L'exigence commune aux deux cas d'utilisation est qu'on a besoin d'un vérificateur de types pour générer des fichiers de déclaration. C'est beaucoup demander à la communauté des outils.

      Cependant, pour les développeurs qui recherchent un temps d'itération rapide et des constructions entièrement parallèles, il y a une autre façon de penser à ce problème. Un fichier de déclaration ne requiert que les types de l'API publique d'un module - en d'autres termes, les types des éléments exportés. Si, ce qui est controversé, les développeurs sont prêts à écrire explicitement les types des choses qu'ils exportent, les outils pourraient générer des fichiers de déclaration sans avoir besoin de regarder l'implémentation du module - et sans réimplémenter un vérificateur de type complet.

      C'est là que la nouvelle option --isolatedDeclarations entre en jeu. --isolatedDeclarations signale les erreurs lorsqu'un module ne peut pas être transformé de manière fiable sans vérificateur de type. Plus simplement, elle fait en sorte que TypeScript signale des erreurs si vous avez un fichier qui n'est pas suffisamment annoté sur ses exportations.

    • Pourquoi les erreurs sont-elles souhaitables ?

      Parce que cela signifie que TypeScript peut

      1. Dire d'emblée si d'autres outils auront des problèmes avec la génération de fichiers de déclaration
      2. Fournir une correction rapide pour aider à ajouter ces annotations manquantes.


      Ce mode ne nécessite pas d'annotations partout. Pour les locals, elles peuvent être ignorées, puisqu'elles n'affectent pas l'API publique.


    Utilisation de isolatedDeclarations

    isolatedDeclarations nécessite que les drapeaux declaration ou composite soient également activés.

    Notez qu'isolatedDeclarations ne modifie pas la façon dont TypeScript exécute emit - seulement la façon dont il rapporte les erreurs. Il est important de noter que, comme pour isolatedModules, l'activation de cette fonctionnalité dans TypeScript n'apportera pas immédiatement les avantages potentiels discutés ici. Soyez donc patients et attendez avec impatience les développements futurs dans ce domaine. En gardant les auteurs d'outils à l'esprit, nous devrions également reconnaître qu'aujourd'hui, toutes les déclarations emit de TypeScript ne peuvent pas être facilement reproduites par d'autres outils souhaitant s'en servir comme guide.

    Il est utile de rappeler que isolatedDeclarations devrait être adopté au cas par cas. Il y a une certaine ergonomie pour le développeur qui est perdue en utilisant isolatedDeclarations, et donc ce n'est peut-être pas le bon choix si votre configuration n'exploite pas les deux scénarios mentionnés plus haut. Pour les autres, le travail sur isolatedDeclarations a déjà permis de découvrir de nombreuses optimisations et opportunités pour débloquer différentes stratégies de construction parallèle. En attendant, si vous êtes prêt à faire des compromis, isolatedDeclarations peut être un outil puissant pour accélérer votre processus de construction une fois que l'outil externe sera disponible.


    La variable modèle ${configDir} pour les fichiers de configuration

    Il est courant dans de nombreuses bases de code de réutiliser un fichier tsconfig.json partagé qui sert de « base » à d'autres fichiers de configuration. Pour ce faire, on utilise le champ extends dans un fichier tsconfig.json.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    {
        "extends": "../../tsconfig.base.json",
        "compilerOptions": {
            "outDir": "./dist"
        }
    }
    L'un des problèmes est que tous les chemins dans le fichier tsconfig.json sont relatifs à l'emplacement du fichier lui-même. Cela signifie que si vous avez un fichier tsconfig.base.json partagé qui est utilisé par plusieurs projets, les chemins relatifs ne seront souvent pas utiles dans les projets dérivés. Par exemple, imaginons le fichier tsconfig.base.json suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    {
        "compilerOptions": {
            "typeRoots": [
                "./node_modules/@types"
                "./custom-types"
            ],
            "outDir": "dist"
        }
    }
    Si l'intention de l'auteur était que chaque tsconfig.json qui étend ce fichier devrait :

    1. sortir dans un répertoire dist relatif au tsconfig.json dérivé, et
    2. avoir un répertoire custom-types relatif au tsconfig.json dérivé,

    alors cela ne fonctionnerait pas. Les chemins de typeRoots seraient relatifs à l'emplacement du fichier partagé tsconfig.base.json, et non au projet qui l'étend. Chaque projet qui étend ce fichier partagé devrait déclarer ses propres outDir et typeRoots avec un contenu identique. Cela pourrait être frustrant et difficile à synchroniser entre les projets, et bien que l'exemple ci-dessus utilise typeRoots, il s'agit d'un problème courant pour les chemins et autres options.

    Pour résoudre ce problème, TypeScript 5.5 introduit une nouvelle variable modèle ${configDir}. Lorsque ${configDir} est écrit dans certains champs de chemin d'un fichier tsconfig.json ou jsconfig.json, cette variable est remplacée par le répertoire contenant le fichier de configuration dans une compilation donnée. Cela signifie que le fichier tsconfig.base.json ci-dessus pourrait être réécrit comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    {
        "compilerOptions": {
            "typeRoots": [
                "${configDir}/node_modules/@types"
                "${configDir}/custom-types"
            ],
            "outDir": "${configDir}/dist"
        }
    }
    Désormais, lorsqu'un projet étend ce fichier, les chemins seront relatifs au fichier tsconfig.json dérivé, et non au fichier tsconfig.base.json partagé. Cela facilite le partage des fichiers de configuration entre les projets et garantit une meilleure portabilité des fichiers de configuration.

    Si vous avez l'intention de rendre un fichier tsconfig.json extensible, considérez si un ./ devrait plutôt être écrit avec ${configDir}.


    TypeScript 5.5 apporte d'autres nouveautés, comme :
    • Consultation des dépendances package.json pour la génération de fichiers de déclaration
    • Amélioration de la fiabilité de l'éditeur et du mode veille
    • Optimisation des performances et de la taille
    • Modules ECMAScript de consommation d'API plus faciles à utiliser
    • API transpileDeclaration

    Des changements de comportements sont également notables et des fonctionnnalités obsolètes sont désactivées dans TypeScript 5.5.


    Quelles sont les prochaines étapes ?

    Microsoft :

    À ce stade, TypeScript 5.5 est ce que nous appelons « feature-stable ». TypeScript 5.5 se concentrera sur les corrections de bogues, le polissage et certaines fonctionnalités d'édition à faible risque. Une version candidate sera disponible dans un peu plus d'un mois, suivie d'une version stable peu après. Si vous souhaitez planifier la sortie de cette version, n'oubliez pas de garder un œil sur notre plan d'itération qui indique les dates de sortie et bien d'autres choses encore.

    Remarque : bien que la version bêta soit un excellent moyen d'essayer la prochaine version de TypeScript, vous pouvez également essayer une version nocturne pour obtenir la version la plus récente de TypeScript 5.5 jusqu'à notre candidat à la publication. Nos nightlies sont bien testées et peuvent même être testées uniquement dans votre éditeur.
    Source : Annonce de TypeScript 5.5

    Et vous ?

    Quel est votre avis sur le sujet ?

    Voir aussi :

    Microsoft annonce la disponibilité de TypeScript 5.4. Cette version apporte un nouveau support d'auto-importation pour les importations de sous-chemins

    Microsoft annonce la disponibilité de la version candidate de TypeScript 5.4. Cette version corrige des bogues critiques et contient des changements notables de comportement
    Publication de communiqués de presse en informatique. Contribuez au club : corrections, suggestions, critiques, ... Contactez le service news et Rédigez des actualités

  2. #2
    Membre expérimenté
    Homme Profil pro
    bricoleur par les mots
    Inscrit en
    Avril 2015
    Messages
    720
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : bricoleur par les mots
    Secteur : Distribution

    Informations forums :
    Inscription : Avril 2015
    Messages : 720
    Points : 1 607
    Points
    1 607
    Par défaut
    Quel est votre avis sur le sujet ?
    ça parait tres technique typescript
    Plus vite encore plus vite toujours plus vite.

  3. #3
    Communiqués de presse

    Femme Profil pro
    Traductrice Technique
    Inscrit en
    Juin 2023
    Messages
    1 215
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Traductrice Technique

    Informations forums :
    Inscription : Juin 2023
    Messages : 1 215
    Points : 84 937
    Points
    84 937
    Par défaut Microsoft annonce la disponibilité de la version candidate de TypeScript 5.5
    Microsoft annonce la disponibilité de TypeScript 5.5 RC (Release Candidate), cette version prend en charge les nouvelles méthodes ECMAScript Set et améliore la fiabilité de l'éditeur et du mode veille

    Microsoft annonce la disponibilité de la version candidate de TypeScript 5.5.

    Voici une liste rapide des nouveautés de TypeScript 5.5 :

    • Prédicats de type inférés
    • Réduction du flux de contrôle pour les accès indexés constants
    • Importations de types dans JSDoc
    • Vérification syntaxique des expressions régulières
    • Déclarations isolées
    • La variable modèle ${configDir} pour les fichiers de configuration
    • Consultation des dépendances package.json pour la génération de fichiers de déclaration
    • Amélioration de la fiabilité de l'éditeur et du mode veille
    • Optimisation des performances et de la taille
    • Modules ECMAScript de consommation d'API plus faciles à utiliser
    • API transpileDeclaration


    Une partie de ces nouveautés sont détaillées dans l'annonce de TypeScript 5.5 Beta. Pour TypeScript 5.5 RC, Microsoft a ajouté la prise en charge des nouvelles méthodes ECMAScript Set. De plus, ils ont ajusté le comportement de la nouvelle vérification des expressions régulières de TypeScript pour être légèrement plus indulgent, tout en continuant à faire des erreurs sur les échappements douteux qui ne sont autorisés que par l'annexe B d'ECMAScript.

    Microsoft a également ajouté et documenté encore plus d'optimisations de performance : notamment, la vérification sautée dans transpileModule et les optimisations dans la façon dont TypeScript filtre les types contextuels. Ces optimisations peuvent conduire à des temps de construction et d'itération plus rapides dans de nombreux scénarios courants.

    Nom : 1.jpg
Affichages : 7351
Taille : 10,6 Ko

    Prise en charge des nouvelles méthodes ECMAScript Set

    TypeScript 5.5 déclare de nouvelles méthodes proposées pour le type ECMAScript Set.

    Certaines de ces méthodes, comme union, intersection, différence et symmetricDifference, prennent un autre Set et renvoient un nouveau Set comme résultat. Les autres méthodes, isSubsetOf, isSupersetOf et isDisjointFrom, prennent un autre ensemble et renvoient un booléen. Aucune de ces méthodes ne modifie les ensembles d'origine.


    Consultation des dépendances package.json pour la génération du fichier de déclaration

    Auparavant, TypeScript affichait souvent un message d'erreur du type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    The inferred type of "X" cannot be named without a reference to "Y". This is likely not portable. A type annotation is necessary.
    Cela était souvent dû au fait que la génération du fichier de déclaration de TypeScript se retrouvait dans le contenu de fichiers qui n'avaient jamais été explicitement importés dans un programme. Générer une importation dans un tel fichier pouvait être risqué si le chemin d'accès s'avérait être relatif. Néanmoins, pour les bases de code avec des dépendances explicites dans les dependencies (ou peerDependencies et optionalDependencies) d'un package.json, la génération d'un tel import devrait être sûre sous certains modes de résolution. Ainsi, dans TypeScript 5.5, Microsoft est plus indulgents lorsque c'est le cas, et de nombreuses occurrences de cette erreur devraient disparaître.


    Amélioration de la fiabilité de l'éditeur et du mode veille

    TypeScript a ajouté de nouvelles fonctionnalités ou corrigé la logique existante qui rend le mode --watch et l'intégration de l'éditeur TypeScript plus fiables. Cela devrait se traduire par moins de redémarrages de TSServer/éditeur.

    Rafraîchissement correct des erreurs de l'éditeur dans les fichiers de configuration

    TypeScript peut générer des erreurs pour les fichiers tsconfig.json ; cependant, ces erreurs sont en fait générées lors du chargement d'un projet, et les éditeurs ne demandent généralement pas directement ces erreurs pour les fichiers tsconfig.json. Bien que cela semble être un détail technique, cela signifie que lorsque toutes les erreurs émises dans un fichier tsconfig.json sont corrigées, TypeScript n'émet pas un nouvel ensemble d'erreurs fraîches et vides, et les utilisateurs se retrouvent avec des erreurs périmées à moins qu'ils ne rechargent leur éditeur.

    TypeScript 5.5 émet désormais intentionnellement un événement pour effacer ces erreurs.

    Meilleure gestion des suppressions suivies d'écritures immédiates

    Au lieu d'écraser les fichiers, certains outils choisissent de les supprimer et de créer de nouveaux fichiers à partir de zéro. C'est le cas lors de l'exécution de npm ci, par exemple.

    Si cela peut être efficace pour ces outils, cela peut être problématique pour les scénarios de l'éditeur TypeScript où la suppression d'un fichier surveillé peut l'éliminer ainsi que toutes ses dépendances transitives. La suppression et la création d'un fichier en succession rapide peuvent conduire TypeScript à démanteler un projet entier et à le reconstruire à partir de zéro.

    TypeScript 5.5 a désormais une approche plus nuancée en conservant des parties d'un projet supprimé jusqu'à ce qu'il détecte un nouvel événement de création. Cela devrait permettre à des opérations comme npm ci de mieux fonctionner avec TypeScript.

    Les liens symboliques sont suivis dans les résolutions échouées

    Lorsque TypeScript échoue à résoudre un module, il devra toujours surveiller les chemins de recherche qui ont échoué dans le cas où le module est ajouté plus tard. Auparavant, cela n'était pas fait pour les répertoires liés par des liens symboliques, ce qui pouvait causer des problèmes de fiabilité dans des scénarios de type monorepo lorsqu'une construction se produisait dans un projet mais n'était pas observée dans l'autre. Ce problème devrait être corrigé dans TypeScript 5.5, ce qui signifie que vous n'aurez plus besoin de redémarrer votre éditeur aussi souvent.

    Les références de projet contribuent aux importations automatiques

    Les importations automatiques ne nécessitent plus au moins une importation explicite vers des projets dépendants dans une configuration de référence de projet. Au lieu de cela, les compléments d'auto-importation devraient fonctionner pour tout ce que vous avez listé dans le champ references de votre tsconfig.json.


    Optimisation des performances et de la taille

    Objets monomorphisés dans le service linguistique et l'API publique

    Dans TypeScript 5.0, les objets Node et Symbol avaient un ensemble cohérent de propriétés avec un ordre d'initialisation cohérent. Cela permet de réduire le polymorphisme dans les différentes opérations, ce qui permet aux moteurs d'exécution d'aller chercher les propriétés plus rapidement.

    En apportant ce changement, Microsoft a constaté des gains de vitesse impressionnants dans le compilateur ; cependant, la plupart de ces changements ont été effectués sur les allocateurs internes pour les structures de données. Le service linguistique, ainsi que l'API publique de TypeScript, utilisent un ensemble différent d'allocateurs pour certains objets. Cela a permis au compilateur TypeScript d'être un peu plus léger, car les données utilisées uniquement pour le service de langage ne seraient jamais utilisées dans le compilateur.

    Dans TypeScript 5.5, le même travail de monomorphisation a été effectué pour le service de langage et l'API publique. Cela signifie que votre expérience d'éditeur, et tous les outils de construction qui utilisent l'API TypeScript, deviendront beaucoup plus rapides. En fait, dans ses benchmarks, Microsoft a constaté une accélération de 5 à 8 % des temps de construction lors de l'utilisation des allocateurs de l'API TypeScript publique, et des opérations du service de langage plus rapides de 10 à 20 %. Bien que cela implique une augmentation de la mémoire, Microsoft pense que ce compromis en vaut la peine et espère trouver des moyens de réduire cette surcharge de mémoire. Les choses devraient être beaucoup plus rapides maintenant.

    Nœuds de flux de contrôle monomorphisés

    Dans TypeScript 5.5, les nœuds du graphe de flux de contrôle ont été monomorphisés afin qu'ils conservent toujours une forme cohérente. Ce faisant, les temps de vérification seront souvent réduits d'environ 1%.

    Optimisations du graphe de flux de contrôle

    Dans de nombreux cas, l'analyse du flux de contrôle traverse des nœuds qui ne fournissent aucune nouvelle information. Microsoft a observé qu'en l'absence de terminaison précoce ou d'effets dans les antécédents (ou « dominateurs ») de certains nœuds, ces nœuds pouvaient toujours être ignorés. Ainsi, TypeScript construit désormais ses graphes de flux de contrôle pour tirer parti de cette situation en établissant un lien avec un nœud antérieur qui fournit des informations intéressantes pour l'analyse du flux de contrôle. Cela permet d'obtenir un graphique de flux de contrôle plus plat, qui peut être plus efficace à parcourir. Cette optimisation a permis d'obtenir des gains modestes, mais avec des réductions allant jusqu'à 2 % du temps de construction sur certaines bases de code.

    Vérification omise dans transpileModule et transpileDeclaration

    L'API transpileModule de TypeScript peut être utilisée pour compiler le contenu d'un seul fichier TypeScript en JavaScript. De même, l'API transpileDeclaration peut être utilisée pour générer un fichier de déclaration pour un seul fichier TypeScript. L'un des problèmes posés par ces API est que TypeScript effectue en interne un contrôle de type complet sur l'ensemble du contenu du fichier avant d'émettre la sortie. Cela était nécessaire pour collecter certaines informations qui seraient ensuite utilisées pour la phase d'émission.

    Dans TypeScript 5.5, Microsoft a trouvé un moyen d'éviter d'effectuer une vérification complète, en ne collectant que paresseusement ces informations si nécessaire, et transpileModule et transpileDeclaration activent tous deux cette fonctionnalité par défaut. En conséquence, les outils qui s'intègrent à ces API, comme ts-loader avec transpileOnly et ts-jest, devraient voir une accélération notable. Lors des tests, Microsoft a généralement constaté une accélération de 2 fois du temps de construction en utilisant transpileModule.

    Réduction de la taille des paquets TypeScript

    En tirant parti de la transition vers les modules dans la version 5.0, Microsoft a considérablement réduit la taille globale des paquets TypeScript en faisant en sorte que tsserver.js et typingsInstaller.js importent à partir d'une bibliothèque API commune au lieu d'avoir chacun d'entre eux produisant des paquets autonomes.

    Cela réduit la taille de TypeScript sur le disque de 30,2 Mo à 20,4 Mo, et réduit sa taille emballée de 5,5 Mo à 3,7 Mo !

    Réutilisation de nœuds dans Declaration Emit

    Dans le cadre de l'activation des isolatedDeclarations, Microsoft a considérablement amélioré la fréquence à laquelle TypeScript peut copier directement votre code source d'entrée lors de la production de fichiers de déclaration.

    Notez que les types d'union sont équivalents, mais que l'ordre de l'union est différent. Lors de l'émission du fichier de déclaration, TypeScript a deux possibilités de sortie équivalente.

    La première consiste à utiliser une représentation canonique cohérente pour chaque type. La seconde approche est généralement préférable pour plusieurs raisons :

    • De nombreuses représentations équivalentes encodent encore un certain niveau d'intention qu'il est préférable de préserver dans le fichier de déclaration
    • La production d'une nouvelle représentation d'un type peut être quelque peu coûteuse, il est donc préférable de l'éviter.
    • Les types écrits par l'utilisateur sont généralement plus courts que les représentations de types générées.


    Dans la version 5.5, Microsoft a grandement amélioré le nombre d'endroits où TypeScript peut correctement identifier les endroits où il est sûr et correct d'imprimer les types exactement comme ils ont été écrits dans le fichier d'entrée. Beaucoup de ces cas sont des améliorations de performance invisibles - TypeScript générerait de nouveaux ensembles de nœuds syntaxiques et les sérialiserait dans une chaîne de caractères. Au lieu de cela, TypeScript peut maintenant opérer directement sur les nœuds syntaxiques originaux, ce qui est beaucoup moins coûteux et plus rapide.

    Mise en cache des types contextuels à partir d'unions discriminées

    Lorsque TypeScript demande le type contextuel d'une expression comme un littéral d'objet, il rencontre souvent un type union. Dans ce cas, TypeScript essaie de filtrer les membres de l'union en se basant sur des propriétés connues avec des valeurs bien connues (c'est-à-dire des propriétés discriminantes). Ce travail peut être assez coûteux, surtout si vous vous retrouvez avec un objet composé d'un grand nombre de propriétés. Dans TypeScript 5.5, une grande partie du calcul est mise en cache une fois pour que TypeScript n'ait pas besoin de le recalculer pour chaque propriété de l'objet littéral. Cette optimisation a permis de gagner 250 ms sur la compilation du compilateur TypeScript lui-même.


    Modules ECMAScript de consommation d'API plus faciles à utiliser

    Auparavant, si vous écriviez un module ECMAScript dans Node.js, les importations nommées n'étaient pas disponibles dans le package typescript.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    import { createSourceFile } from "typescript"; //  error
     
    import * as ts from "typescript";
    ts.createSourceFile //  undefined???
     
    ts.default.createSourceFile //  works - but ugh!
    En effet, cjs-module-lexer ne reconnaissait pas le modèle de code CommonJS généré par TypeScript. Ce problème a été corrigé et les utilisateurs peuvent désormais utiliser les importations nommées du paquetage TypeScript npm avec les modules ECMAScript dans Node.js.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    import { createSourceFile } from "typescript"; //  works now!
     
    import * as ts from "typescript";
    ts.createSourceFile //  works now!

    L'API transpileDeclaration

    L'API TypeScript expose une fonction appelée transpileModule. Elle est destinée à faciliter la compilation d'un seul fichier de code TypeScript. Comme elle n'a pas accès à un programme entier, elle risque de ne pas produire le bon résultat si le code ne respecte pas les erreurs de l'option isolatedModules.

    Dans TypeScript 5.5, Microsoft a ajouté une nouvelle API similaire appelée transpileDeclaration. Cette API est similaire à transpileModule, mais elle est spécifiquement conçue pour générer un seul fichier de déclaration basé sur un texte source d'entrée. Tout comme transpileModule, elle n'a pas accès à un programme complet, et une mise en garde similaire s'applique : elle ne génère un fichier de déclaration précis que si le code d'entrée est exempt d'erreurs en vertu de la nouvelle option isolatedDeclarations.

    Si vous le souhaitez, cette fonction peut être utilisée pour paralléliser l'émission de déclarations dans tous les fichiers en mode isolatedDeclarations. Notez que, bien que vous puissiez ressentir une partie de la surcharge de performance de transpileModule dans transpileDeclaration, Microsoft travaille sur des moyens d'optimiser cela davantage.


    Des changements de comportements sont également notables dans TypeScript 5.5. Parmi les changements, on peut noter :

    • Désactivation des fonctionnalités obsolètes dans TypeScript 5.0
    • Changements dans lib.d.ts
    • Respect des extensions de fichiers et de package.json dans d'autres modes de modules
    • Parsing plus strict pour les décorateurs
    • undefined n'est plus un nom de type définissable
    • Déclaration simplifiée de la directive de référence Emit


    Quelles sont les prochaines étapes ?

    Microsoft :

    À ce stade, nous prévoyons très peu de changements pour TypeScript 5.5 en dehors des corrections de bogues critiques pour le compilateur et des corrections de bogues mineurs pour le service de langage. Dans les prochaines semaines, nous publierons la première version stable de TypeScript 5.5. Gardez un œil sur notre plan d'itération pour connaître les dates de sortie et plus si vous avez besoin de vous coordonner.

    Sinon, nous nous concentrons sur le développement de TypeScript 5.6, et nous aurons le plan d'itération disponible dans les prochains jours (y compris les dates de sortie prévues). De plus, nous facilitons l'utilisation des nightly builds de TypeScript sur npm, et il existe une extension pour utiliser ces nightly releases dans Visual Studio Code.
    Source : Annonce Typescript 5.5 RC

    Et vous ?

    Quel est votre avis sur le sujet ?

    Voir aussi :

    Microsoft annonce la disponibilité de TypeScript 5.5 Beta, cette version apporte les prédicats de type inférés et réduit le flux de controle pour les accès indexés constants

    Microsoft annonce la disponibilité de la version candidate de TypeScript 5.4, cette version corrige des bogues critiques et contient des changements notables de comportement
    Publication de communiqués de presse en informatique. Contribuez au club : corrections, suggestions, critiques, ... Contactez le service news et Rédigez des actualités

  4. #4
    Communiqués de presse

    Femme Profil pro
    Traductrice Technique
    Inscrit en
    Juin 2023
    Messages
    1 215
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Traductrice Technique

    Informations forums :
    Inscription : Juin 2023
    Messages : 1 215
    Points : 84 937
    Points
    84 937
    Par défaut Microsoft annonce la disponibilité de TypeScript 5.5
    Microsoft annonce la disponibilité de TypeScript 5.5, cette version apporte les prédicats de type inférés, les déclarations isolées, ainsi qu'une amélioration de la fiabilité de l'éditeur.

    Microsoft annonce la disponibilité de TypeScript 5.5. Parmi les nouveautés : Prédicats de type inférés, réduction du flux de contrôle pour les accès indexés constants, vérification syntaxique des expressions régulières, les déclarations isolées, amélioration de la fiabilité de l'éditeur et du mode veille, et optimisation des performances et de la taille, et bien plus encore.

    TypeScript est un langage qui s'appuie sur JavaScript en permettant de déclarer et de décrire des types. Écrire des types dans le code permet d'expliquer l'intention et de faire vérifier le code par d'autres outils pour détecter les erreurs comme les fautes de frappe, les problèmes avec null et undefined, et bien plus encore.

    Les types alimentent également les outils d'édition de TypeScript, comme l'auto-complétion, la navigation dans le code et les refactorisations que vous pouvez voir dans des éditeurs tels que Visual Studio et VS Code. En fait, si vous écrivez du JavaScript dans l'un ou l'autre de ces éditeurs, cette expérience est alimentée par TypeScript.

    Depuis la version Beta, Microsoft a ajouté la prise en charge des nouvelles méthodes ECMAScript Set. De plus, ils ont ajusté le comportement de la nouvelle vérification des expressions régulières de TypeScript pour être légèrement plus indulgent, tout en continuant à faire des erreurs sur les échappements douteux qui ne sont autorisés que par l'annexe B d'ECMAScript.

    Microsoft a également ajouté et documenté encore plus d'optimisations de performance : notamment, la vérification sautée dans transpileModule et les optimisations dans la façon dont TypeScript filtre les types contextuels. Ces optimisations peuvent conduire à des temps de construction et d'itération plus rapides dans de nombreux scénarios courants.

    Nom : 1.jpg
Affichages : 10055
Taille : 10,6 Ko

    Depuis la version candidate (RC), Microsoft est revenu temporairement sur sa nouvelle méthode de travail qui consistait à consulter le fichier package.json pour déterminer le format de module d'un fichier donné. ce changement perturbait certains flux de travail et causait une pression inattendue sur la surveillance des fichiers pour les grands projets. Dans TypeScript 5.6, Microsoft espère ramener une version plus nuancée de cette fonctionnalité, tout en cherchant à optimiser la façon de surveiller les fichiers inexistants.

    Des changements de comportements sont également notables dans TypeScript 5.5. Parmi les changements, on peut noter : Désactivation des fonctionnalités obsolètes dans TypeScript 5.0, changements dans lib.d.ts, respect des extensions de fichiers et de package.json dans d'autres modes de modules, parsing plus strict pour les décorateurs, undefined n'est plus un nom de type définissable, et déclaration simplifiée de la directive de référence Emit.

    Voici une liste rapide des nouveautés de TypeScript 5.5 :

    • Prédicats de type inférés
    • Réduction du flux de contrôle pour les accès indexés constants
    • La balise @import de JSDoc
    • Vérification syntaxique des expressions régulières
    • Déclarations isolées
    • La variable modèle ${configDir} pour les fichiers de configuration
    • Consultation des dépendances package.json pour la génération de fichiers de déclaration
    • Amélioration de la fiabilité de l'éditeur et du mode veille
    • Optimisation des performances et de la taille
    • Modules ECMAScript de consommation d'API plus faciles à utiliser
    • API transpileDeclaration




    Prédicats de type inférés

    L'analyse du flux de contrôle de TypeScript fait un excellent travail de suivi de la façon dont le type d'une variable change au fur et à mesure qu'elle se déplace dans votre code :

    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
    interface Bird {
        commonName: string;
        scientificName: string;
        sing(): void;
    }
     
    // Maps country names -> national bird.
    // Not all nations have official birds (looking at you, Canada!)
    declare const nationalBirds: Map<string, Bird>;
     
    function makeNationalBirdCall(country: string) {
      const bird = nationalBirds.get(country);  // bird has a declared type of Bird | undefined
      if (bird) {
        bird.sing();  // bird has type Bird inside the if statement
      } else {
        // bird has type undefined here.
      }
    }
    En vous obligeant à gérer les cas indéfinis, TypeScript vous pousse à écrire un code plus robuste.

    Dans le passé, ce type de raffinement de type était plus difficile à appliquer aux tableaux. Cela aurait été une erreur dans toutes les versions précédentes de TypeScript :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function makeBirdCalls(countries: string[]) {
      // birds: (Bird | undefined)[]
      const birds = countries
        .map(country => nationalBirds.get(country))
        .filter(bird => bird !== undefined);
     
      for (const bird of birds) {
        bird.sing();  // error: 'bird' is possibly 'undefined'.
      }
    }
    Ce code est parfaitement correct : ils ont filtré toutes les valeurs indéfinies de la liste. Mais TypeScript n'a pas été en mesure de suivre le mouvement.

    Avec TypeScript 5.5, le vérificateur de type n'a rien à redire à ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function makeBirdCalls(countries: string[]) {
      // birds: Bird[]
      const birds = countries
        .map(country => nationalBirds.get(country))
        .filter(bird => bird !== undefined);
     
      for (const bird of birds) {
        bird.sing();  // ok!
      }
    }
    Notez le type plus précis pour les birds.

    Cela fonctionne parce que TypeScript déduit maintenant un prédicat de type pour la fonction de filtrage. Vous pouvez voir plus clairement ce qui se passe en la transformant en une fonction indépendante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // function isBirdReal(bird: Bird | undefined): bird is Bird
    function isBirdReal(bird: Bird | undefined) {
      return bird !== undefined;
    }
    bird is Bird est le prédicat de type. Cela signifie que si la fonction renvoie true, il s'agit d'un bird (si la fonction renvoie false, il s'agit d'un indéfini). Les déclarations de type pour Array.prototype.filter connaissent les prédicats de type, de sorte que le résultat net est que vous obtenez un type plus précis et que le code passe le vérificateur de type.

    TypeScript déduira qu'une fonction renvoie un prédicat de type si ces conditions sont remplies :

    1. La fonction n'a pas d'annotation explicite de type de retour ou de prédicat de type.
    2. La fonction a un seul énoncé de retour et aucun retour implicite.
    3. La fonction ne modifie pas son paramètre.
    4. La fonction renvoie une expression booléenne liée à un raffinement du paramètre.


    En règle générale, tout se passe comme prévu. Voici quelques autres exemples de prédicats de types déduits :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // const isNumber: (x: unknown) => x is number
    const isNumber = (x: unknown) => typeof x === 'number';
     
    // const isNonNullish: <T>(x: T) => x is NonNullable<T>
    const isNonNullish = <T,>(x: T) => x != null;
    Auparavant, TypeScript aurait simplement déduit que ces fonctions renvoient une expression booléenne. Il déduit maintenant les signatures avec des prédicats de type comme x est un nombre ou x est NonNullable<T>.

    Les prédicats de type ont une sémantique « si et seulement si ». Si une fonction renvoie x is T, cela signifie que :

    1. Si la fonction renvoie un résultat vrai, x est de type T.
    2. Si la fonction renvoie faux, x n'est pas de type T.


    Si vous vous attendez à ce qu'un prédicat de type soit déduit mais qu'il ne l'est pas, vous risquez de vous heurter à la deuxième règle. Ce problème se pose souvent dans le cadre des vérifications de « véracité » :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function getClassroomAverage(students: string[], allScores: Map<string, number>) {
      const studentScores = students
        .map(student => allScores.get(student))
        .filter(score => !!score);
     
      return studentScores.reduce((a, b) => a + b) / studentScores.length;
      //     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      // error: Object is possibly 'undefined'.
    }
    TypeScript n'a pas déduit de prédicat de type pour score => !!score, et ce à juste titre : si ce prédicat retourne vrai, alors score est un nombre. Mais s'il renvoie false, alors score peut être soit indéfini, soit un nombre (en particulier, 0). Il s'agit d'un véritable bogue : si un étudiant a obtenu un zéro à l'examen, le fait de filtrer son score faussera la moyenne vers le haut. Moins d'élèves seront au-dessus de la moyenne et plus d'élèves seront tristes !

    Comme dans le premier exemple, il est préférable de filtrer explicitement les valeurs indéfinies :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function getClassroomAverage(students: string[], allScores: Map<string, number>) {
      const studentScores = students
        .map(student => allScores.get(student))
        .filter(score => score !== undefined);
     
      return studentScores.reduce((a, b) => a + b) / studentScores.length;  // ok!
    }
    Un contrôle de véracité déduira un prédicat de type pour les types d'objets, là où il n'y a pas d'ambiguïté. Rappelez-vous que les fonctions doivent retourner un booléen pour être candidates à un prédicat de type inféré : x => !!x peut inférer un prédicat de type, mais x => x ne le fera certainement pas.

    Les prédicats de type explicites continuent à fonctionner exactement comme avant. TypeScript ne vérifiera pas s'il déduit le même prédicat de type. Les prédicats de type explicites (« is ») ne sont pas plus sûrs qu'une assertion de type (« as »).

    Il est possible que cette fonctionnalité casse du code existant si TypeScript déduit maintenant un type plus précis que ce que vous souhaitez. Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // Previously, nums: (number | null)[]
    // Now, nums: number[]
    const nums = [1, 2, 3, null, 5].filter(x => x !== null);
     
    nums.push(null);  // ok in TS 5.4, error in TS 5.5
    La solution consiste à indiquer à TypeScript le type que vous souhaitez en utilisant une annotation de type explicite :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    const nums: (number | null)[] = [1, 2, 3, null, 5].filter(x => x !== null);
    nums.push(null);  // ok in all versions

    Réduction du flux de contrôle pour les accès indexés constants

    TypeScript est désormais capable de réduire les expressions de la forme obj[key] lorsque obj et key sont effectivement constants.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    function f1(obj: Record<string, unknown>, key: string) {
        if (typeof obj[key] === "string") {
            // Now okay, previously was error
            obj[key].toUpperCase();
        }
    }
    Dans l'exemple ci-dessus, ni obj ni key ne sont jamais mutés, donc TypeScript peut limiter le type de obj[key] à string après la vérification de typeof.


    La balise @import de JSDoc

    Aujourd'hui, si vous voulez importer quelque chose uniquement pour vérifier le type dans un fichier JavaScript, c'est encombrant. Les développeurs JavaScript ne peuvent pas simplement importer un type nommé SomeType s'il n'est pas présent au moment de l'exécution.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // ./some-module.d.ts
    export interface SomeType {
        // ...
    }
     
    // ./index.js
    import { SomeType } from "./some-module"; //  runtime error!
     
    /**
     * @param {SomeType} myValue
     */
    function doSomething(myValue) {
        // ...
    }
    SomeType n'existera pas au moment de l'exécution, et l'importation échouera. Les développeurs peuvent à la place utiliser une importation d'espace de noms.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    import * as someModule from "./some-module";
     
    /**
     * @param {someModule.SomeType} myValue
     */
    function doSomething(myValue) {
        // ...
    }
    Mais ./some-module est toujours importé à l'exécution, ce qui n'est pas forcément souhaitable.

    Pour éviter cela, les développeurs devaient généralement utiliser des types import(...) dans les commentaires JSDoc.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    /**
     * @param {import("./some-module").SomeType} myValue
     */
    function doSomething(myValue) {
        // ...
    }
    Si vous vouliez réutiliser le même type à plusieurs endroits, vous pouviez utiliser un typedef pour éviter de répéter l'importation.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /**
     * @typedef {import("./some-module").SomeType} SomeType
     */
     
    /**
     * @param {SomeType} myValue
     */
    function doSomething(myValue) {
        // ...
    }
    Cela est utile pour les utilisations locales de SomeType, mais cela devient répétitif pour de nombreuses importations et peut être un peu verbeux.

    C'est pourquoi TypeScript prend désormais en charge une nouvelle balise de commentaire @import qui a la même syntaxe que les importations ECMAScript.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    /** @import { SomeType } from "some-module" */
     
    /**
     * @param {SomeType} myValue
     */
    function doSomething(myValue) {
        // ...
    }
    Ici, ils ont utilisé des importations nommées. Ils auraient également pu écrire l'importation comme une importation d'espace de noms.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    /** @import * as someModule from "some-module" */
     
    /**
     * @param {someModule.SomeType} myValue
     */
    function doSomething(myValue) {
        // ...
    }
    Comme il ne s'agit que de commentaires JSDoc, ils n'affectent en rien le comportement à l'exécution.


    Vérification syntaxique des expressions régulières

    Jusqu'à présent, TypeScript a généralement ignoré la plupart des expressions régulières dans le code. En effet, les expressions régulières ont techniquement une grammaire extensible et TypeScript n'a jamais fait d'effort pour compiler les expressions régulières dans les versions antérieures de JavaScript. Néanmoins, cela signifiait que de nombreux problèmes courants n'étaient pas découverts dans les expressions régulières et qu'ils se transformaient en erreurs au moment de l'exécution ou échouaient silencieusement.

    Mais TypeScript effectue désormais un contrôle syntaxique de base sur les expressions régulières !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    let myRegex = /@robot(\s+(please|immediately)))? do some task/;
    //                                            ~
    // error!
    // Unexpected ')'. Did you mean to escape it with backslash?
    Il s'agit d'un exemple simple, mais cette vérification peut permettre de détecter de nombreuses erreurs courantes. En fait, le contrôle de TypeScript va un peu plus loin que les contrôles syntaxiques. Par exemple, TypeScript peut maintenant détecter les problèmes liés à des références arrière qui n'existent pas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    let myRegex = /@typedef \{import\((.+)\)\.([a-zA-Z_]+)\} \3/u;
    //                                                        ~
    // error!
    // This backreference refers to a group that does not exist.
    // There are only 2 capturing groups in this regular expression.
    Il en va de même pour les groupes de capture nommés.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    let myRegex = /@typedef \{import\((?<importPath>.+)\)\.(?<importedEntity>[a-zA-Z_]+)\} \k<namedImport>/;
    //                                                                                        ~~~~~~~~~~~
    // error!
    // There is no capturing group named 'namedImport' in this regular expression.
    La vérification de TypeScript est désormais également consciente de l'utilisation de certaines fonctionnalités RegExp lorsque celles-ci sont plus récentes que votre version cible d'ECMAScript. Par exemple, si on utilise des groupes de capture nommés comme ci-dessus dans une cible ES5, on obtiendra une erreur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    let myRegex = /@typedef \{import\((?<importPath>.+)\)\.(?<importedEntity>[a-zA-Z_]+)\} \k<importedEntity>/;
    //                                  ~~~~~~~~~~~~         ~~~~~~~~~~~~~~~~
    // error!
    // Named capturing groups are only available when targeting 'ES2018' or later.
    Il en va de même pour certains drapeaux d'expressions régulières.

    Notez que la prise en charge des expressions régulières par TypeScript est limitée aux expressions régulières littérales. Si vous essayez d'appeler new RegExp avec une chaîne littérale, TypeScript ne vérifiera pas la chaîne fournie.


    Prise en charge des nouvelles méthodes ECMAScript Set

    TypeScript 5.5 déclare de nouvelles méthodes proposées pour le type ECMAScript Set.

    Certaines de ces méthodes, comme union, intersection, différence et symmetricDifference, prennent un autre [CSet[/C] et renvoient un nouveau Set comme résultat. Les autres méthodes, isSubsetOf, isSupersetOf et isDisjointFrom, prennent un autre ensemble et renvoient un booléen. Aucune de ces méthodes ne modifie les ensembles d'origine.


    Déclarations isolées

    Les fichiers de déclaration (alias fichiers .d.ts) décrivent la forme des bibliothèques et modules existants en TypeScript. Cette description légère comprend les signatures de type de la bibliothèque et exclut les détails d'implémentation tels que les corps des fonctions. Ils sont publiés afin que TypeScript puisse vérifier efficacement votre utilisation d'une bibliothèque sans avoir besoin d'analyser la bibliothèque elle-même. Bien qu'il soit possible d'écrire à la main des fichiers de déclaration, si vous écrivez du code typé, il est beaucoup plus sûr et plus simple de laisser TypeScript les générer automatiquement à partir des fichiers source en utilisant --declaration.

    Le compilateur TypeScript et ses API ont toujours été chargés de générer les fichiers de déclaration ; cependant, dans certains cas d'utilisation, il est préférable d'utiliser d'autres outils, ou le processus de construction traditionnel n'est pas adapté.

    • Cas d'utilisation : Outils d'émission de déclarations plus rapides

      Imaginez que vous souhaitiez créer un outil plus rapide pour générer des fichiers de déclaration, peut-être dans le cadre d'un service de publication ou d'un nouveau bundler. S'il existe un écosystème florissant d'outils ultra-rapides capables de transformer TypeScript en JavaScript, il n'en va pas de même pour la transformation de TypeScript en fichiers de déclaration. La raison en est que l'inférence de TypeScript nous permet d'écrire du code sans déclarer explicitement les types, ce qui signifie que l'émission de déclarations peut être complexe.

      Bien que cette inférence soit importante pour le développeur, cela signifie que les outils qui souhaitent générer des fichiers de déclaration devraient reproduire certaines parties du vérificateur de type, notamment l'inférence et la capacité à résoudre les spécificateurs de modules pour suivre les importations.

    • Cas d'utilisation : Déclaration parallèle Emit et vérification parallèle

      Imaginez que vous ayez une monorepo contenant de nombreux projets et un processeur multicœur qui souhaiterait vous aider à vérifier votre code plus rapidement. Ne serait-ce pas génial si nous pouvions vérifier tous ces projets en même temps en exécutant chaque projet sur un cœur différent ?

      Malheureusement, on n'a pas la liberté de faire tout le travail en parallèle. La raison est qu'on doit construire ces projets dans l'ordre des dépendances, parce que chaque projet vérifie les fichiers de déclaration de ses dépendances. On doit donc construire la dépendance en premier pour générer les fichiers de déclaration. La fonction de références de projet de TypeScript fonctionne de la même manière, en construisant l'ensemble des projets dans l'ordre de dépendance « topologique ».

      Nom : 1.jpg
Affichages : 763
Taille : 22,2 Ko

      Comment pourrait-on améliorer cela ? Eh bien, si un outil rapide pouvait générer tous ces fichiers de déclaration pour le noyau en parallèle, TypeScript pourrait immédiatement suivre en vérifiant le type du noyau, du frontend et du backend également en parallèle.

    • Solution : Types explicites !

      L'exigence commune aux deux cas d'utilisation est qu'on a besoin d'un vérificateur de types pour générer des fichiers de déclaration. C'est beaucoup demander à la communauté des outils.

      Cependant, pour les développeurs qui recherchent un temps d'itération rapide et des constructions entièrement parallèles, il y a une autre façon de penser à ce problème. Un fichier de déclaration ne requiert que les types de l'API publique d'un module - en d'autres termes, les types des éléments exportés. Si, ce qui est controversé, les développeurs sont prêts à écrire explicitement les types des choses qu'ils exportent, les outils pourraient générer des fichiers de déclaration sans avoir besoin de regarder l'implémentation du module - et sans réimplémenter un vérificateur de type complet.

      C'est là que la nouvelle option --isolatedDeclarations entre en jeu. --isolatedDeclarations signale les erreurs lorsqu'un module ne peut pas être transformé de manière fiable sans vérificateur de type. Plus simplement, elle fait en sorte que TypeScript signale des erreurs si vous avez un fichier qui n'est pas suffisamment annoté sur ses exportations.

    • Pourquoi les erreurs sont-elles souhaitables ?

      Parce que cela signifie que TypeScript peut

      1. Dire d'emblée si d'autres outils auront des problèmes avec la génération de fichiers de déclaration
      2. Fournir une correction rapide pour aider à ajouter ces annotations manquantes.


      Ce mode ne nécessite pas d'annotations partout. Pour les locals, elles peuvent être ignorées, puisqu'elles n'affectent pas l'API publique.


    Utilisation de isolatedDeclarations

    isolatedDeclarations nécessite que les drapeaux declaration ou composite soient également activés.

    Notez qu'isolatedDeclarations ne modifie pas la façon dont TypeScript exécute emit - seulement la façon dont il rapporte les erreurs. Il est important de noter que, comme pour isolatedModules, l'activation de cette fonctionnalité dans TypeScript n'apportera pas immédiatement les avantages potentiels discutés ici. Soyez donc patients et attendez avec impatience les développements futurs dans ce domaine. En gardant les auteurs d'outils à l'esprit, nous devrions également reconnaître qu'aujourd'hui, toutes les déclarations emit de TypeScript ne peuvent pas être facilement reproduites par d'autres outils souhaitant s'en servir comme guide.

    Il est utile de rappeler que isolatedDeclarations devrait être adopté au cas par cas. Il y a une certaine ergonomie pour le développeur qui est perdue en utilisant isolatedDeclarations, et donc ce n'est peut-être pas le bon choix si votre configuration n'exploite pas les deux scénarios mentionnés plus haut. Pour les autres, le travail sur isolatedDeclarations a déjà permis de découvrir de nombreuses optimisations et opportunités pour débloquer différentes stratégies de construction parallèle. En attendant, si vous êtes prêt à faire des compromis, isolatedDeclarations peut être un outil puissant pour accélérer votre processus de construction une fois que l'outil externe sera disponible.


    La variable modèle ${configDir} pour les fichiers de configuration

    Il est courant dans de nombreuses bases de code de réutiliser un fichier tsconfig.json partagé qui sert de « base » à d'autres fichiers de configuration. Pour ce faire, on utilise le champ extends dans un fichier tsconfig.json.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    {
        "extends": "../../tsconfig.base.json",
        "compilerOptions": {
            "outDir": "./dist"
        }
    }
    L'un des problèmes est que tous les chemins dans le fichier tsconfig.json sont relatifs à l'emplacement du fichier lui-même. Cela signifie que si vous avez un fichier tsconfig.base.json partagé qui est utilisé par plusieurs projets, les chemins relatifs ne seront souvent pas utiles dans les projets dérivés. Par exemple, imaginons le fichier tsconfig.base.json suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    {
        "compilerOptions": {
            "typeRoots": [
                "./node_modules/@types"
                "./custom-types"
            ],
            "outDir": "dist"
        }
    }
    Si l'intention de l'auteur était que chaque tsconfig.json qui étend ce fichier devrait :

    1. sortir dans un répertoire dist relatif au tsconfig.json dérivé, et
    2. avoir un répertoire custom-types relatif au tsconfig.json dérivé,

    alors cela ne fonctionnerait pas. Les chemins de typeRoots seraient relatifs à l'emplacement du fichier partagé tsconfig.base.json, et non au projet qui l'étend. Chaque projet qui étend ce fichier partagé devrait déclarer ses propres outDir et typeRoots avec un contenu identique. Cela pourrait être frustrant et difficile à synchroniser entre les projets, et bien que l'exemple ci-dessus utilise typeRoots, il s'agit d'un problème courant pour les chemins et autres options.

    Pour résoudre ce problème, TypeScript 5.5 introduit une nouvelle variable modèle ${configDir}. Lorsque ${configDir} est écrit dans certains champs de chemin d'un fichier tsconfig.json ou jsconfig.json, cette variable est remplacée par le répertoire contenant le fichier de configuration dans une compilation donnée. Cela signifie que le fichier tsconfig.base.json ci-dessus pourrait être réécrit comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    {
        "compilerOptions": {
            "typeRoots": [
                "${configDir}/node_modules/@types"
                "${configDir}/custom-types"
            ],
            "outDir": "${configDir}/dist"
        }
    }
    Désormais, lorsqu'un projet étend ce fichier, les chemins seront relatifs au fichier tsconfig.json dérivé, et non au fichier tsconfig.base.json partagé. Cela facilite le partage des fichiers de configuration entre les projets et garantit une meilleure portabilité des fichiers de configuration.

    Si vous avez l'intention de rendre un fichier tsconfig.json extensible, considérez si un ./ devrait plutôt être écrit avec ${configDir}.


    Consultation des dépendances package.json pour la génération du fichier de déclaration

    Auparavant, TypeScript affichait souvent un message d'erreur du type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    The inferred type of "X" cannot be named without a reference to "Y". This is likely not portable. A type annotation is necessary.
    Cela était souvent dû au fait que la génération du fichier de déclaration de TypeScript se retrouvait dans le contenu de fichiers qui n'avaient jamais été explicitement importés dans un programme. Générer une importation dans un tel fichier pouvait être risqué si le chemin d'accès s'avérait être relatif. Néanmoins, pour les bases de code avec des dépendances explicites dans les dependencies (ou peerDependencies et optionalDependencies) d'un package.json, la génération d'un tel import devrait être sûre sous certains modes de résolution. Ainsi, dans TypeScript 5.5, Microsoft est plus indulgents lorsque c'est le cas, et de nombreuses occurrences de cette erreur devraient disparaître.


    Amélioration de la fiabilité de l'éditeur et du mode veille

    TypeScript a ajouté de nouvelles fonctionnalités ou corrigé la logique existante qui rend le mode --watch et l'intégration de l'éditeur TypeScript plus fiables. Cela devrait se traduire par moins de redémarrages de TSServer/éditeur.

    Rafraîchissement correct des erreurs de l'éditeur dans les fichiers de configuration

    TypeScript peut générer des erreurs pour les fichiers tsconfig.json ; cependant, ces erreurs sont en fait générées lors du chargement d'un projet, et les éditeurs ne demandent généralement pas directement ces erreurs pour les fichiers tsconfig.json. Bien que cela semble être un détail technique, cela signifie que lorsque toutes les erreurs émises dans un fichier tsconfig.json sont corrigées, TypeScript n'émet pas un nouvel ensemble d'erreurs fraîches et vides, et les utilisateurs se retrouvent avec des erreurs périmées à moins qu'ils ne rechargent leur éditeur.

    TypeScript 5.5 émet désormais intentionnellement un événement pour effacer ces erreurs.

    Meilleure gestion des suppressions suivies d'écritures immédiates

    Au lieu d'écraser les fichiers, certains outils choisissent de les supprimer et de créer de nouveaux fichiers à partir de zéro. C'est le cas lors de l'exécution de npm ci, par exemple.

    Si cela peut être efficace pour ces outils, cela peut être problématique pour les scénarios de l'éditeur TypeScript où la suppression d'un fichier surveillé peut l'éliminer ainsi que toutes ses dépendances transitives. La suppression et la création d'un fichier en succession rapide peuvent conduire TypeScript à démanteler un projet entier et à le reconstruire à partir de zéro.

    TypeScript 5.5 a désormais une approche plus nuancée en conservant des parties d'un projet supprimé jusqu'à ce qu'il détecte un nouvel événement de création. Cela devrait permettre à des opérations comme npm ci de mieux fonctionner avec TypeScript.

    Les liens symboliques sont suivis dans les résolutions échouées

    Lorsque TypeScript échoue à résoudre un module, il devra toujours surveiller les chemins de recherche qui ont échoué dans le cas où le module est ajouté plus tard. Auparavant, cela n'était pas fait pour les répertoires liés par des liens symboliques, ce qui pouvait causer des problèmes de fiabilité dans des scénarios de type monorepo lorsqu'une construction se produisait dans un projet mais n'était pas observée dans l'autre. Ce problème devrait être corrigé dans TypeScript 5.5, ce qui signifie que vous n'aurez plus besoin de redémarrer votre éditeur aussi souvent.

    Les références de projet contribuent aux importations automatiques

    Les importations automatiques ne nécessitent plus au moins une importation explicite vers des projets dépendants dans une configuration de référence de projet. Au lieu de cela, les compléments d'auto-importation devraient fonctionner pour tout ce que vous avez listé dans le champ references de votre tsconfig.json.


    Optimisation des performances et de la taille

    Objets monomorphisés dans le service linguistique et l'API publique

    Dans TypeScript 5.0, les objets Node et Symbol avaient un ensemble cohérent de propriétés avec un ordre d'initialisation cohérent. Cela permet de réduire le polymorphisme dans les différentes opérations, ce qui permet aux moteurs d'exécution d'aller chercher les propriétés plus rapidement.

    En apportant ce changement, Microsoft a constaté des gains de vitesse impressionnants dans le compilateur ; cependant, la plupart de ces changements ont été effectués sur les allocateurs internes pour les structures de données. Le service linguistique, ainsi que l'API publique de TypeScript, utilisent un ensemble différent d'allocateurs pour certains objets. Cela a permis au compilateur TypeScript d'être un peu plus léger, car les données utilisées uniquement pour le service de langage ne seraient jamais utilisées dans le compilateur.

    Dans TypeScript 5.5, le même travail de monomorphisation a été effectué pour le service de langage et l'API publique. Cela signifie que votre expérience d'éditeur, et tous les outils de construction qui utilisent l'API TypeScript, deviendront beaucoup plus rapides. En fait, dans ses benchmarks, Microsoft a constaté une accélération de 5 à 8 % des temps de construction lors de l'utilisation des allocateurs de l'API TypeScript publique, et des opérations du service de langage plus rapides de 10 à 20 %. Bien que cela implique une augmentation de la mémoire, Microsoft pense que ce compromis en vaut la peine et espère trouver des moyens de réduire cette surcharge de mémoire. Les choses devraient être beaucoup plus rapides maintenant.

    Nœuds de flux de contrôle monomorphisés

    Dans TypeScript 5.5, les nœuds du graphe de flux de contrôle ont été monomorphisés afin qu'ils conservent toujours une forme cohérente. Ce faisant, les temps de vérification seront souvent réduits d'environ 1%.

    Optimisations du graphe de flux de contrôle

    Dans de nombreux cas, l'analyse du flux de contrôle traverse des nœuds qui ne fournissent aucune nouvelle information. Microsoft a observé qu'en l'absence de terminaison précoce ou d'effets dans les antécédents (ou « dominateurs ») de certains nœuds, ces nœuds pouvaient toujours être ignorés. Ainsi, TypeScript construit désormais ses graphes de flux de contrôle pour tirer parti de cette situation en établissant un lien avec un nœud antérieur qui fournit des informations intéressantes pour l'analyse du flux de contrôle. Cela permet d'obtenir un graphique de flux de contrôle plus plat, qui peut être plus efficace à parcourir. Cette optimisation a permis d'obtenir des gains modestes, mais avec des réductions allant jusqu'à 2 % du temps de construction sur certaines bases de code.

    Vérification omise dans transpileModule et transpileDeclaration

    L'API transpileModule de TypeScript peut être utilisée pour compiler le contenu d'un seul fichier TypeScript en JavaScript. De même, l'API transpileDeclaration peut être utilisée pour générer un fichier de déclaration pour un seul fichier TypeScript. L'un des problèmes posés par ces API est que TypeScript effectue en interne un contrôle de type complet sur l'ensemble du contenu du fichier avant d'émettre la sortie. Cela était nécessaire pour collecter certaines informations qui seraient ensuite utilisées pour la phase d'émission.

    Dans TypeScript 5.5, Microsoft a trouvé un moyen d'éviter d'effectuer une vérification complète, en ne collectant que paresseusement ces informations si nécessaire, et transpileModule et transpileDeclaration activent tous deux cette fonctionnalité par défaut. En conséquence, les outils qui s'intègrent à ces API, comme ts-loader avec transpileOnly et ts-jest, devraient voir une accélération notable. Lors des tests, Microsoft a généralement constaté une accélération de 2 fois du temps de construction en utilisant transpileModule.

    Réduction de la taille des paquets TypeScript

    En tirant parti de la transition vers les modules dans la version 5.0, Microsoft a considérablement réduit la taille globale des paquets TypeScript en faisant en sorte que tsserver.js et typingsInstaller.js importent à partir d'une bibliothèque API commune au lieu d'avoir chacun d'entre eux produisant des paquets autonomes.

    Cela réduit la taille de TypeScript sur le disque de 30,2 Mo à 20,4 Mo, et réduit sa taille emballée de 5,5 Mo à 3,7 Mo !

    Réutilisation de nœuds dans Declaration Emit

    Dans le cadre de l'activation des isolatedDeclarations, Microsoft a considérablement amélioré la fréquence à laquelle TypeScript peut copier directement votre code source d'entrée lors de la production de fichiers de déclaration.

    Notez que les types d'union sont équivalents, mais que l'ordre de l'union est différent. Lors de l'émission du fichier de déclaration, TypeScript a deux possibilités de sortie équivalente.

    La première consiste à utiliser une représentation canonique cohérente pour chaque type. La seconde approche est généralement préférable pour plusieurs raisons :

    • De nombreuses représentations équivalentes encodent encore un certain niveau d'intention qu'il est préférable de préserver dans le fichier de déclaration
    • La production d'une nouvelle représentation d'un type peut être quelque peu coûteuse, il est donc préférable de l'éviter.
    • Les types écrits par l'utilisateur sont généralement plus courts que les représentations de types générées.


    Dans la version 5.5, Microsoft a grandement amélioré le nombre d'endroits où TypeScript peut correctement identifier les endroits où il est sûr et correct d'imprimer les types exactement comme ils ont été écrits dans le fichier d'entrée. Beaucoup de ces cas sont des améliorations de performance invisibles - TypeScript générerait de nouveaux ensembles de nœuds syntaxiques et les sérialiserait dans une chaîne de caractères. Au lieu de cela, TypeScript peut maintenant opérer directement sur les nœuds syntaxiques originaux, ce qui est beaucoup moins coûteux et plus rapide.

    Mise en cache des types contextuels à partir d'unions discriminées

    Lorsque TypeScript demande le type contextuel d'une expression comme un littéral d'objet, il rencontre souvent un type union. Dans ce cas, TypeScript essaie de filtrer les membres de l'union en se basant sur des propriétés connues avec des valeurs bien connues (c'est-à-dire des propriétés discriminantes). Ce travail peut être assez coûteux, surtout si vous vous retrouvez avec un objet composé d'un grand nombre de propriétés. Dans TypeScript 5.5, une grande partie du calcul est mise en cache une fois pour que TypeScript n'ait pas besoin de le recalculer pour chaque propriété de l'objet littéral. Cette optimisation a permis de gagner 250 ms sur la compilation du compilateur TypeScript lui-même.


    Modules ECMAScript de consommation d'API plus faciles à utiliser

    Auparavant, si vous écriviez un module ECMAScript dans Node.js, les importations nommées n'étaient pas disponibles dans le package typescript.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    import { createSourceFile } from "typescript"; //  error
     
    import * as ts from "typescript";
    ts.createSourceFile //  undefined???
     
    ts.default.createSourceFile //  works - but ugh!
    En effet, cjs-module-lexer ne reconnaissait pas le modèle de code CommonJS généré par TypeScript. Ce problème a été corrigé et les utilisateurs peuvent désormais utiliser les importations nommées du paquetage TypeScript npm avec les modules ECMAScript dans Node.js.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    import { createSourceFile } from "typescript"; //  works now!
     
    import * as ts from "typescript";
    ts.createSourceFile //  works now!

    L'API transpileDeclaration

    L'API TypeScript expose une fonction appelée transpileModule. Elle est destinée à faciliter la compilation d'un seul fichier de code TypeScript. Comme elle n'a pas accès à un programme entier, elle risque de ne pas produire le bon résultat si le code ne respecte pas les erreurs de l'option isolatedModules.

    Dans TypeScript 5.5, Microsoft a ajouté une nouvelle API similaire appelée transpileDeclaration. Cette API est similaire à transpileModule, mais elle est spécifiquement conçue pour générer un seul fichier de déclaration basé sur un texte source d'entrée. Tout comme transpileModule, elle n'a pas accès à un programme complet, et une mise en garde similaire s'applique : elle ne génère un fichier de déclaration précis que si le code d'entrée est exempt d'erreurs en vertu de la nouvelle option isolatedDeclarations.

    Si vous le souhaitez, cette fonction peut être utilisée pour paralléliser l'émission de déclarations dans tous les fichiers en mode isolatedDeclarations. Notez que, bien que vous puissiez ressentir une partie de la surcharge de performance de transpileModule dans transpileDeclaration, Microsoft travaille sur des moyens d'optimiser cela davantage.


    Quelle est la prochaine étape ?

    La prochaine version de TypeScript sera TypeScript 5.6, et Microsoft prévoit une sortie au début du mois de septembre 2024 (dans quelques mois). Vous pouvez essayer les premières versions de TypeScript 5.6 dès aujourd'hui en installant les nightly builds depuis npm avec npm install _D typescript@next, ou en utilisant l'extension VS Code TypeScript Nightly. Gardez un œil sur le plan d'itération à venir, qui contiendra des dates cibles précises et des fonctionnalités. D'ici là, TypeScript 5.5 est là et prêt à l'emploi !

    Source : Annonce de Typescript 5.5

    Et vous ?

    Quel est votre avis sur cette annonce ?

    Voir aussi :

    Microsoft annonce la disponibilité de TypeScript 5.5 RC (Release Candidate), cette version prend en charge les nouvelles méthodes ECMAScript Set et améliore la fiabilité de l'éditeur et du mode veille

    Microsoft annonce la disponibilité de TypeScript 5.5 Beta, cette version apporte les prédicats de type inférés et réduit le flux de controle pour les accès indexés constants

    Microsoft annonce la disponibilité de TypeScript 5.4, cette version apporte un nouveau support d'auto-importation pour les importations de sous-chemins
    Publication de communiqués de presse en informatique. Contribuez au club : corrections, suggestions, critiques, ... Contactez le service news et Rédigez des actualités

Discussions similaires

  1. Microsoft annonce la disponibilité de TypeScript 5.4 Beta
    Par Jade Emy dans le forum TypeScript
    Réponses: 2
    Dernier message: 07/03/2024, 11h53
  2. Microsoft annonce la disponibilité de TypeScript 5.2 Beta.
    Par Nancy Rey dans le forum TypeScript
    Réponses: 2
    Dernier message: 10/08/2023, 10h46
  3. Réponses: 0
    Dernier message: 28/03/2018, 00h20
  4. Microsoft annonce la disponibilité de TypeScript 2.4
    Par Stéphane le calme dans le forum TypeScript
    Réponses: 1
    Dernier message: 28/06/2017, 07h38
  5. Réponses: 0
    Dernier message: 23/02/2017, 12h12

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