Sortie de TypeScript 3.8

Par:
fredericmazue

ven, 21/02/2020 - 13:32

Après une version bêta publié mi janvier, TypeScript 3.8 arrive en version finale.

Cette nouvelle version se fait principalement remarquer par une nouvelle fonctionnalité permettant d'importer/exporter des types seuls.

Soit un exemple comme celui-ci :

// ./foo.ts
interface Options {
    // ...
}

export function doThing(options: Options) {
    // ...
}

// ./bar.ts
import { doThing, Options } from "./foo.js";

function doThingBetter(options: Options) {
    // do something twice as good
    doThing(options);
    doThing(options);

Le code est légal, mais le problème est que lorsque TypeScript va produire le code JavaScript correspondant, il va se rendre compte que Option n'est qu'un type et va passer son importation à la trappe.

Une nouvelle syntaxe vient en solution de ce problème et permet désormais d'importer/exporter des types seuls :

import type { SomeThing } from "./some-module.js";
export type { SomeThing };

Une autre évolution importante est l'arrivée du support des champs privés ECMAScript. Soit cet exemple de code :

class Person {
    #name: string

    constructor(name: string) {
        this.#name = name;
    }

    greet() {
        console.log(`Hello, my name is ${this.#name}!`);
    }
}
let jeremy = new Person("Jeremy Bearimy");
jeremy.#name
//     ~~~~~
// Property '#name' is not accessible outside class 'Person'
// because it has a private identifier.

Un champ privé doit débuter par le caractère # et sa portée est limitée à sa classe. Les modificateurs d'accessibilité tels que public ou private ne peuvent pas être utilisés avec les champs privés. Il n'est pas possible d'accéder ou même de détecter un champ privé en dehors de sa classe, même avec du code JavaScript. Cette particularité induit l'unicité des champs privés. Par exemple, un champ classique est partagé par plusieurs instances comme ceci :

class C {
    foo = 10;

    cHelper() {
        return this.foo;
    }
}

class D extends C {
    foo = 20;

    dHelper() {
        return this.foo;
    }
}

let instance = new D();
// 'this.foo' refers to the same property on each instance.
console.log(instance.cHelper()); // prints '20'
console.log(instance.dHelper()); // prints '20'

Mais un champ privé reste unique, spécifique à sa classe :

class C {
    #foo = 10;

    cHelper() {
        return this.#foo;
    }
}

class D extends C {
    #foo = 20;

    dHelper() {
        return this.#foo;
    }
}

let instance = new D();
// 'this.#foo' refers to a different field within each class.
console.log(instance.cHelper()); // prints '10'
console.log(instance.dHelper()); // prints '20'