Sortie de TypeScript 3.7

Par:
fredericmazue

mer, 06/11/2019 - 11:56

Microsoft vient de publier TypeScript 3.7. Cette nouvelle mouture du langage apporte des nouveautés intéressantes. En voici deux :

Le chainage d'optionnels

Le chainage d'optionnels que l'on trouve dans quelques autres langages comme par exemple Swift, permet de n'exécuter du code que lorsqu'un optionnel à une valeur. En TypeScript, avoir une valeur signifie ne pas être null ou undefined. L'opérateur du chainage optionnel est ?. et il s'utilise ainsi :

let x = foo?.bar.baz();

Ce qui signifie que qui foo n'est ni null ni undefined, alors, alors foo.bar.bar(); sera exécuté et le résultat affecté à la variable x. Comme l'explique le billet de Microsoft, cela aura pu être écrit, beaucoup plus lourdement, avec le classique opérateur ternaire ?

let x = (foo === null || foo === undefined) ?
    undefined :
    foo.bar.baz();

Avec cet exemple, Microsoft fait remarquer que si baz est null ou undefined, le code provoque malgré tout une erreur. Il n'y a que ce qui est à gauche de l'opérateur de chainage optionnel ?. qui est testé. Le chainage optionnel est intéressant pour parcourir des arborescences.

La coalescence null (Nullish Coalescing)

L'opérateur de coalescence null ?? permet de se rebattre sur une valeur par défaut (de définir un fallback) lorsque la valeur testée est null ou undefined. Par exemple :

let x = foo ?? bar();

signifie que si foo existe, sa valeur sera affecté à x, et si foo est null ou undefined, c'est le résultat de bar(); qui sera affecté à x.

Sans l'opérateur de coalescence null ??, ceci s'écrit beaucoup plus lourdement :

let x = (foo !== null && foo !== undefined) ?
    foo :
    bar();

Attention cette version introduit plusieurs changements qui vont casser la compatibilité avec les codes actuels dont :

- typeArguments a été retiré. Il faut utiliser getTypeArguments sur les instances de TypeChecker.

- en raison d'un bug, le code suivant était jusqu'ici accepté par TypeScript:

// ./someOtherModule.ts
interface SomeType {
    y: string;
}

// ./myModule.ts
import { SomeType } from "./someOtherModule";
export interface SomeType {
    x: number;
}

function fn(arg: SomeType) {
    console.log(arg.x); // Error! 'x' doesn't exist on 'SomeType'
}

Ceci est maintenant corrigé et ce code provoque une erreur de duplication d'identifiant.