Description
Consider two TypeScript files:
_a.ts_
module M {
export var t = 5;
}
_b.ts_
var t = 'foo';
module M {
var s = t; // <-- what does this mean?
}
If we compile b.ts on its own, the t
in var s = t
refers to the outer var t
, a string
. The emit for this line is simply var s = t;
.
If we compile b.ts along with a.ts, the t
in var s = t
refers to M.t
, the exported variable of type number
. The emit for this line is var s = M.t
.
This behavior, and a few other language features (e.g. const enum
), prevent TypeScript from being able to correctly operate on a single file without understanding the entire universe of files involved in the program. This has performance implications for features like compile-on-save, especially in larger projects, and blocks scenarios like on-the-fly compilation in module loaders.
We'd really prefer to be able to emit a file without first understanding the entire program it's a part of. The language as-is prevents this. However, by slightly subsetting the language to disallow things that require whole-program binding/typechecking, we can re-enable those scenarios. People can "opt in" their project to this language subset as a trade-off.
Tentatively, we're calling the prongs of this fork "whole program mode" and "single file mode". Naming TBD.
A key part of this is that you need to be able to compile e.g. a.ts and b.ts above in a mode that says "This code will not work in single-file-mode", e.g.:
> tsc --warnMeIfThisIsNotSafeInSingleFileMode a.ts b.ts
TS1234 (b.ts line 2): Modules may not be re-opened in single-file mode
We need some help naming these things, especially the commandline flag. The current list of ideas on the whiteboard, of which nobody likes anything, consists of the following 😦
separateCompile
singleFileEmit
disableGlobalOptimizations
safeForTranspile
safeForSyntacticTranspilation
separate
isolated
safeTransform
singleFileScope
crossFileSafe
crossFileRestrictions
Please help 🚲 🏠!
Ref #2499