Een uitgebreide gids voor “Module System” in TypeScript (met voorbeelden)
On oktober 16, 2021 by adminModule Standard
EcmaScript heeft gestandaardiseerd hoe we modules moeten importeren in JavaScript en deze standaard draait om twee sleutelwoorden, import
en export
. Aangezien het modulesysteem in JavaScript steeds populairder wordt, komen er elk jaar enkele nieuwe wijzigingen in deze standaard.
In deze tutorial gaan we kijken naar de semantiek van het modulesysteem in TypeScript (dat grotendeels lijkt op de EcmaScript-standaard) en hoe import
en export
keyword werken.
Named Exports
Het export
keyword maakt een waarde (variabele) gedefinieerd in een bestand beschikbaar voor import in andere modulebestanden. Wanneer een module wordt geïmporteerd in een ander module bestand met behulp van import
keyword, kan het importerende bestand de waarden specificeren die het wil benaderen van de geïmporteerde module.
// program.ts
import { A } from 'path/to/values';console.log( A ); // "Apple"
In het bovenstaande voorbeeld importeren we values.ts
in het program.ts
bestand en extraheren we het A
geëxporteerde lid. Dit betekent dat values.ts
de waarde A
in enigerlei vorm moet exporteren. Er zijn meerdere manieren om A
te exporteren.
// values.ts
var A = "Apple"; // can also use `let` or `const`
class B {}
function C(){}
enum D{}export { A, B, C, D };
U kunt elke toegankelijke TypeScript waarde exporteren met een geldige identifier (naam). In dit voorbeeld exporteren we een variabele A
(kan ook een constante zijn), klasse B
, enzovoort. Met de syntax export {}
kunt u zoveel waarden exporteren als u wilt en iedereen kan ze importeren met de syntax import { A, B }
. U hoeft niet alle geëxporteerde waarden te importeren.
Er is een andere manier om een waarde te exporteren waar deze is gedeclareerd.
// values.ts
export const A = { name: "Apple" };
export class B {}
export function C(){}
export enum D{}
In het bovenstaande voorbeeld hebben we alle waarden geëxporteerd waar ze zijn gedeclareerd. U hoeft de waarde ook niet te initialiseren, dat kunt u later in het bestand doen. Dit is een veel mooiere manier dan de vorige.
In beide gevallen zijn al je export leden toegankelijk binnen hetzelfde bestand als je ze nodig hebt om te gebruiken. Het export
sleutelwoord op een waarde verandert zijn gedrag niet binnen het module bestand.
Default Export
Tot nu toe hebben we waarden geëxporteerd die alleen kunnen worden geïmporteerd door de naam van export leden op te geven, zoals import { A } from 'path/to/values'
waar A
hier een export lid is van values.ts
. Dit worden named exports genoemd.
Het is ook toegestaan een enkele waarde te exporteren die kan worden geïmporteerd zonder een naam op te geven. Deze waarde moet worden geïdentificeerd met het sleutelwoord default
samen met het sleutelwoord export
.
// values.ts
var A = "Apple"; // can also use `let` or `const`
class A {}
function A(){}
enum A{}export default A;
U mag slechts een enkele waarde exporteren als standaardexport, vandaar dat u geen export default {...}
expressie hebt om mee te werken. In tegenstelling tot named exports, kan een waarde niet als standaard worden geëxporteerd met een variabele (of constante) declaratie, behalve een function
en class
declaratie.
// values.ts
export default var A = "Apple"; // ❌ invalid syntax
export default enum D{} // ❌ illegal: not a function or class
export default class B {} // ✅ legal
export default function C(){} // ✅ legal
U kunt echter wel een waarde direct exporteren als standaardexport. Dit betekent dat elke JavaScript-expressie kan worden geëxporteerd als de standaardexportwaarde.
// values.ts
export default "Hello"; // string
export default {}; // object
export default () => undefined; // function
export default function(){}; // function
export default class{}; // class
Omdat standaardexport geen exportnaam heeft, kunnen we er tijdens het importeren een willekeurige naam aan geven. U kunt exports met een naam en een standaardexport in hetzelfde modulebestand hebben. Op dezelfde manier kunt u de standaardexport en benoemde exportwaarden in een enkele import
-declaratie importeren, zoals hieronder wordt getoond.
import Apple, { B, C } from 'path/to/values';
In het bovenstaande voorbeeld is de Apple
de naam die we hebben gebruikt om de standaardexport op te halen uit de values.ts
. U kunt de { B, C }
expressie of Apple
naam uit de import
declaratie laten vallen als u deze niet gaat gebruiken.
💡 Net als bij named exports is het niet verplicht om de standaard exportwaarde te importeren wanneer
import
declaratie wordt gebruikt. Maar deApple
moet vóór de named exports komen in deimport
-declaratiehandtekening.
U kunt ook de as default
-syntaxis in de export {}
-handtekening gebruiken om een waarde als standaardwaarde te exporteren samen met andere named exports. Dit heet aliasing en wordt uitgelegd in de volgende sectie.
// values.ts
var A = "Apple"; // can also use `let` or `const`
class B {}
function C(){}
enum D{}export { A as default, B, C, D };
💡 De reden waarom ik
default
-export niet gebruik en ook niet aanbeveel, heeft te maken met de ervaring van ontwikkelaars. Zoals we geleerd hebben, kun je in deimport
declaratie elke willekeurige naam opgeven voor de standaard export memeber van een module. Als deze waarde in meerdere bestanden wordt geïmporteerd, kunt u ernaar verwijzen met elke naam van uw keuze en het hebben van verschillende namen voor hetzelfde exportlid van dezelfde module is een slechte DX.
Import And Export Alias
In het geval van de standaardexport, kunt u naar de waarde verwijzen met elke naam van uw keuze in de import
-declaratie. Dat is echter niet het geval bij named exports. U kunt echter het as
sleutelwoord gebruiken om te verwijzen naar een benoemde exportwaarde met de naam van uw keuze.
// program.ts
import A, { B as Ball } from 'path/to/values';console.log( B ); // ❌ Error: Cannot find name 'B'.
console.log( Ball ); // ✅ legal
In het bovenstaande voorbeeld importeren we B
uit values.ts
, maar het heeft een andere naam gekregen: Ball
. Daarom zou u in het program.ts
bestand Apple
gebruiken in plaats van B
. Wanneer u een export member aliast, bestaat de oorspronkelijke naam niet meer in het globale bereik, dus B
zal niet meer bestaan in program.ts
.
💡 U kunt het standaard export member niet aliasen omdat u al een naam naar keuze kunt opgeven, maar u kunt
import { default as defaultValue, }
gebruiken.
U kunt een waarde ook een alias geven tijdens het exporteren met het trefwoord as
.
// values.ts
var A = "Apple"; // can also use `let` or `const`
class B {}
function C(){}
enum D{}export { A as default, B, C as Cat, D };
In het bovenstaande voorbeeld hebben we variabele A
als standaardexport en functie C
als Cat
geëxporteerd. Daarom moet iedereen die deze waarden importeert uit een values.ts
-bestand de standaard importsyntaxis gebruiken voor A
en Cat
voor de C
-waarde.
Importeer alle genoemde exports
U kunt alle genoemde exports uit een bestand importeren met behulp van de * as
-syntaxis.
// program.ts
import Apple, * as values from 'path/to/values';console.log( values.B );
console.log( values.C );
console.log( values.D );
Alle benoemde exports uit values.ts
worden opgeslagen onder values
, een object met keys
als de naam van de export members en values
als de geëxporteerde waarden van de export members.
Her-uitvoer
Een geïmporteerde waarde kan op de normale manier opnieuw worden geëxporteerd. Wanneer u iets importeert, hebt u een verwijzing naar de importwaarde en kunt u dezelfde waarde gebruiken in de export
syntaxis. Daar is niets mis mee.
// lib.ts
import A, { B, C as Cat, D } from 'path/to/values';export { D as default, A, B, Cat as C, D };
In het bovenstaande voorbeeld heeft u een paar waarden uit values.ts
geïmporteerd in lib.ts
en geëxporteerd volgens uw voorkeur. Dit is geweldig als u deze invoer in lib.ts
wilt gebruiken en sommige ervan wilt exporteren als een ander bestand ze nodig heeft wanneer het importeert uit lib.ts
.
Echter, we hebben ook export ... from
statement om waarden uit een bestand te exporteren zonder ze eerst te hoeven importeren. Dit is geweldig wanneer u een enkel punt van binnenkomst wilt houden voor alle importen in uw module.
// lib.ts// re-exports
export { P as Paper, Q } from 'path/to/values-1';
export { N, O as Orange } from 'path/to/other/values-2';// default export
export default "hello";class B {}
function C(){}// named exports
export { B, C as Cat };
In het bovenstaande voorbeeld exporteren we enkele van de export leden van values-1.ts
en values-2.ts
uit het lib.ts
bestand (behalve de standaard export). We kunnen ook aliasing gebruiken in de export ... from
syntax.
De re-export syntax heeft geen invloed op het huidige bestand, dus u kunt uw reguliere exports ook in het bestand hebben, zoals hierboven getoond. In tegenstelling tot export
keyword, geeft de export ... from
syntaxis geen toegang tot opnieuw geëxporteerde leden. U zult dus geen toegang hebben tot P
of Orange
in het lib.ts
bestand.
// lib.ts
export { P as Paper, Q } from 'path/to/values-1';
export { N, O as Orange } from 'path/to/other/values-2';console.log( P ); // ❌ Error: Cannot find name 'P'.
console.log( Orange ); // ❌ Error: Cannot find name 'Orange'.
U kunt alle benoemde exports van een bestand exporteren met de export * from
syntaxis als u de mogelijkheid hebt om ze te hernoemen tijdens het exporteren met export * as ... from
.
// lib.ts
export * from 'path/to/values-1';
export * as values2 from 'path/to/other/values-2';
In het bovenstaande voorbeeld, als values-1.ts
P
en Q
exporteert, dan kan iedereen P
en Q
importeren uit lib.ts
. Alle named exports van values-2.ts
worden echter opnieuw geëxporteerd als values2
named exports van lib.ts
, vandaar dat u ze moet importeren met de volgende syntaxis.
// program.ts
import { P, Q, values2 } from 'path/to/lib';
U kunt de standaardexport niet op een normale manier benaderen met de syntaxis export ... from
. Maar u kunt de standaardexport exporteren met behulp van het default
sleutelwoord.
// lib.ts
export { default } from 'path/to/values-1';
export { default as Apple } from 'path/to/values-2';
In het bovenstaande voorbeeld is de standaardexport van lib.ts
de standaardexportwaarde van values-2.ts
. De standaardexportwaarde van values-2
wordt geëxporteerd uit lib.ts
als de Apple
met de naam export.
Import voor neveneffect
Kunt u zich voorstellen dat u een bestand importeert zonder de geëxporteerde leden op te geven?
import 'path/to/action';
In bovenstaand voorbeeld importeren we action.ts
, maar we hebben alle leden opgegeven die door de action.ts
worden geëxporteerd. Dit is een geldige syntaxis, maar het geeft een heel ander resultaat.
Wanneer u een bestand importeert met het import
sleutelwoord, wordt het eerst uitgevoerd en dan zijn alle export leden beschikbaar voor import. Vandaar dat in het onderstaande voorbeeld, een bestand dat PI
importeert, de 3.14
als een floating-point
nummer zou krijgen.
export const PI = parseFloat( "3.14" ); // 3.14
Volgens dezelfde logica, als u een neveneffect wilt creëren door een bestand te importeren, dan kunt u dat volledig doen. Dus als er bijvoorbeeld een bestand is dat een aantal globale variabelen initialiseert, dan kun je dat importeren zonder de geëxporteerde leden van dat bestand te specificeren (het zou er ook geen kunnen exporteren).
TypeScript compiler kan een JavaScript bundel bestand (.js
) maken door twee of meer .ts
bestanden samen te compileren. Dit wordt normaal gesproken gedaan door een entry TypeScript-bestand op te geven en vervolgens de afhankelijkheidsboom ervan te doorlopen.
Een afhankelijkheidsboom wordt opgebouwd door te kijken naar alle import
-verklaringen (afhankelijkheden) van het entry-bestand en de afhankelijkheden van deze geïmporteerde bestanden te volgen. Als u een bestand wilt opnemen waarvan de code tijdens runtime neveneffecten kan veroorzaken, dan moet u dat bestand importeren zonder de geëxporteerde leden in de import
syntaxis te specificeren. Dit kan worden gedaan in het invoerbestand of in elk bestand dat zich binnen de afhankelijkheidsboom bevindt.
Geef een antwoord