Typescript: Synlighed inden for samme navneområde på tværs af flere filer
Kan du hjælpe mig - er dette en fejl, eller misforstår jeg dokumentationen?
Jeg har to filer i et namespace - du vil finde en enklere version nedenfor.
Typescript-dokumentationen angiver, at "Selvom filerne er separate, kan de hver især bidrage til det samme namespace og kan bruges, som om de alle var defineret i én". Derfor ville jeg antage, at en klasse fra én fil kunne få adgang til en anden fil inden for det samme namespace, selvom den ikke var eksporteret. (Fordi det ville være tilfældet, hvis de blev defineret på samme sted)
Men tsc klager over, at det ikke kan finde navnet "Dispatcher". Hvorfor sker dette? Misforstår jeg dokumentationen på dette tidspunkt? Eller er det bare en compiler-fejl? Det ville være en skam, hvis det var det første, fordi visibilitet kun inden for namespace ville hjælpe meget til enhedstestning og indkapsling.
Kode :
(koden ændret for enkelhed. Hvis der er syntaksfejl, skyldes det det):
Application.ts:
/// <reference path="Dispatcher.ts"/>
namespace Application {
export class Application {
constructor() {
new Dispatcher();
}
}
}
Dispatcher.ts:
namespace Application {
class Dispatcher { /* ... */ }
}
Svar #1
Typescript-dokumentationen angiver, at "Selvom filerne er separate, kan de hver især bidrage til det samme navnerum og kan bruges, som om de alle var defineret i ét."
Det afhænger af den præcise definition af "bidrage til samme navnerum". Den nuværende tolkning er "alt, der eksporteres, er tilgængeligt overalt, alt, der ikke eksporteres, er kun tilgængeligt inden for den del af navnerummet, hvor det er defineret". Sådan forklares det i sprogspecifikationen:
Namespaces giver en mekanisme til at organisere kode og erklæringer i hierarkier af navngivne containere. Namespaces har navngivne medlemmer, der hver angiver en værdi, en type eller et namespace, eller en kombination deraf, og disse medlemmer kan være lokale eller eksporterede. Kroppen af et namespace svarer til en funktion, der udføres én gang, hvilket giver en mekanisme til at opretholde lokal tilstand med sikret isolation. Namespaces kan betragtes som en formalisering af mønstret med umiddelbart-påkaldes-funktioner (IIFE).
Hvis der er flere erklæringer af samme namespace, kompileres hver enkelt til en separat IIFE, som det kan ses i den kompilerede javascriptkode for Dispatcher.ts:
var Application;
(function (Application) {
class Dispatcher {
}
})(Application || (Application = {}));
Resultatet er, at Dispatcher er scoped inde i funktionen, og det er ikke tilgængeligt udefra.
Selv hvis du havde namespace Application gentaget to gange i samme fil, ville hver definere sin egen kopi af Dispatcher - der er ingen fejl i denne kode:
namespace Application {
class Dispatcher { /* ... */ }
}
namespace Application {
class Dispatcher { /* ... */ }
}
Den eneste måde at gøre Dispatcher tilgængelig fra uden for namespace { ... } er at eksportere det. Med eksport bliver Dispatcher en egenskab af Application-objektet:
namespace Application {
export class Dispatcher { /* ... */ }
}
kompileret kode:
var Application;
(function (Application) {
class Dispatcher {
}
Application.Dispatcher = Dispatcher;
})(Application || (Application = {}));
Denne adfærd giver mening implementeringsmæssigt. Det ville være virkelig besværligt at implementere namespaces, så ikke-eksporterede objekter blev delt mellem alle namespace-instanser, men ikke kunne tilgås udefra.
