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

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

TypeScript 3.8 RC apporte une nouvelle syntaxe pour l'importation/exportation de types uniquement
Ainsi que les champs privés ECMAScript

Le , par Stéphane le calme

272PARTAGES

10  0 
Imports et exports d'un type en particulier

TypeScript réutilise la syntaxe d'importation de JavaScript afin de nous permettre de référencer les types. Par exemple, dans l'exemple suivant, nous pouvons importer doThing qui est une valeur JavaScript avec Options qui est purement un type TypeScript.

Code TypeScript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ./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); 
}

C'est pratique parce que la plupart du temps, nous n'avons pas à nous soucier de ce qui est importé, mais uniquement de nous assurer que nous importons bien quelque chose. Malheureusement, cela n'a fonctionné qu'en raison d'une fonctionnalité appelée élision d'importation. Lorsque TypeScript génère des fichiers JavaScript, il voit que Options n'est utilisé que comme type et supprime automatiquement son importation. La sortie résultante ressemble un peu à ceci:

Code TypeScript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
// ./foo.js 
export function doThing(options: Options) { 
    // ... 
} 
  
// ./bar.js 
import { doThing } from "./foo.js"; 
  
function doThingBetter(options: Options) { 
    // do something twice as good 
    doThing(options); 
    doThing(options); 
}

Encore une fois, ce comportement est généralement bien, mais il provoque d'autres problèmes. Tout d’abord, il existe des endroits où il est ambigu d’exporter une valeur ou un type. Par exemple, dans l'exemple suivant, MyThing est-il une valeur ou un type ?

Code TypeScript : Sélectionner tout
1
2
3
import { MyThing } from "./some-module.js"; 
  
export { MyThing };

En nous limitant à ce fichier, il n'y a aucun moyen de le savoir. L'API transpileModule de Babel et de TypeScript émettra du code qui ne fonctionnera pas correctement si MyThing n'est qu'un type, et l'indicateur isolatedModules de TypeScript nous avertira que ce sera un problème. Le vrai problème ici est qu'il n'y a aucun moyen de dire « non non, en fait je voulais faire appel au type, ceci devrait être effacé », donc l'importation d'élision n'est pas suffisante.

L’autre problème était que l’élision d’importation de TypeScript supprimait les instructions d’importation qui ne contenaient que les importations utilisées comme types. Cela a provoqué un comportement sensiblement différent pour les modules qui ont des effets secondaires, et les utilisateurs devraient donc insérer une deuxième instruction d'importation uniquement pour contrer les effets secondaires.

Code TypeScript : Sélectionner tout
1
2
3
4
5
// This statement will get erased because of import elision. 
import { SomeTypeFoo, SomeOtherTypeBar } from "./module-with-side-effects"; 
  
// This statement always sticks around. 
import "./module-with-side-effects";

Un cas concret où l'équipe TypeScript a vu cela arriver était dans des frameworks comme Angular.js (1.x) où les services devaient être enregistrés globalement (ce qui est un effet secondaire), mais où ces services n'étaient importés que pour les types.

Code TypeScript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
// ./service.ts 
export class Service { 
    // ... 
} 
register("globalServiceId", Service); 
  
// ./consumer.ts 
import { Service } from "./service.js"; 
  
inject("globalServiceId", function (service: Service) { 
    // do stuff with Service 
});

Par conséquent, ./service.js ne sera jamais exécuté et les choses vont planter lors de l'exécution.

Pour éviter ce type de problèmes, l'équipe a réalisé qu'elle devait donner aux utilisateurs un contrôle plus fin sur la façon dont les choses étaient importées/élidées.

En tant que solution dans TypeScript 3.8, l'équipe a ajouté une nouvelle syntaxe pour les importations et exportations de type uniquement.

Code TypeScript : Sélectionner tout
1
2
3
import type { SomeThing } from "./some-module.js"; 
  
export type { SomeThing };

import type importe uniquement les déclarations à utiliser pour les annotations et les déclarations de type. Il est toujours entièrement effacé, il n'y a donc pas de reste à l'exécution. De même, export type fournit uniquement une exportation qui peut être utilisée pour les contextes de type et est également effacé de la sortie de TypeScript.

Il est important de noter que les classes ont une valeur au moment de l'exécution et un type au moment du design, et l'utilisation est très sensible au contexte. Lorsque vous utilisez import type pour importer une classe, vous ne pouvez pas faire des choses comme faire une extension à partir de celle-ci.

Code TypeScript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
import type { Component } from "react"; 
  
interface ButtonProps { 
    // ... 
} 
  
class Button extends Component<ButtonProps> { 
    //               ~~~~~~~~~ 
    // error! 'Component' only refers to a type, but is being used as a value here. 
  
    // ... 
}

Si vous avez déjà utilisé Flow, la syntaxe est assez similaire. Une différence est que l'équipe TypeScript a ajouté quelques restrictions pour éviter le code qui pourrait apparaître ambigu.

Code TypeScript : Sélectionner tout
1
2
3
4
5
6
// Is only 'Foo' a type? Or every declaration in the import? 
// We just give an error because it's not clear. 
  
import type Foo, { Bar, Baz } from "some-module"; 
//     ~~~~~~~~~~~~~~~~~~~~~~ 
// error! A type-only import can specify a default import or named bindings, but not both.

En conjonction avec import type, l...
La fin de cet article est réservée aux abonnés. Soutenez le Club Developpez.com en prenant un abonnement pour que nous puissions continuer à vous proposer des publications.

Une erreur dans cette actualité ? Signalez-nous-la !