I have 2 TypeScript modules like below. In the second module when I import a module, the classes, modules in the same namespace won't be accessible ( seems they don't exist ).
MyName.Modules.ts:
module MyName.Modules{
export class Class1 {
Name:string;
}
}
MyName.Modules.Extras.ts:
/// <reference path="MyName.Modules.ts"/>
/// <reference path="nunjucks.d.ts"/>
/* if I comment this line of code MyName.Modules.Class1 is available
and if I won't do it TypeScript compiler can't find it.
*/
import * as nunjucks from "nunjucks";
module MyName.Modules.Extas{
export class Class2 extends MyName.Modules.Class1 {
public DoNothing():void{
}
}
}
P.S: nunjucks.d.ts is just an example, It doesn't matter what you import ...
Isn't it related to the rule below?
Red Flags: https://www.typescriptlang.org/docs/handbook/modules.html
Multiple files that have the same export namespace Foo { at top-level (don鈥檛 think that these are going to combine into one Foo!)
When a file begins with a top level import or export statement, it represents an _external_ module. This means that all of its exports must be imported explicitly. The first _module_ you have written is what has been called an _internal_ module or a namespace (the dedicated namespace keyword is now available and should be used to disambiguate internal vs external modules).
Anyway, I recommend something like
MyName/Modules/Core.ts:
export class Class1 {
Name:string;
}
MyName/Modules/Extras.ts:
import * as nunjucks from "nunjucks";
import { Class1 } from "./Core";
export class Class2 extends Class1 {
public DoNothing(): void {
}
}
You will need to set the compilerOptions.module property in your IDE/tsconfig.json.
EDIT: correct paths and formatting
Need to add this to the FAQ.
@aluanhaddad Thanks. It'll solve my problem.
P.S:
Yesterday I read TypeScript handbook but I didn't find you mentioned.
FAQ entry: https://github.com/Microsoft/TypeScript/wiki/FAQ#why-did-adding-an-import-or-export-modifier-break-my-program
This needs to be re-designed. If later on an import is required into a file that originally had no imports, that would create a ripple effect throughout the entire code base.
use --module none if you do not intend to use modules, this way you will get an error once you have a top-level import or export.
Didn't say I don't intend to use modules. The simple fact that an import extracts that particular file out of its original scope and isolates it into a module, without even bringing the original namespace originally spaced out across multiple files with it, is simply a cop-out design for this feature.
Correct me if I'm wrong, but from that point onwards every single file would need an import referencing the original, not to mention that now the other files now become modules as well. The whole namespace gets destroyed.
If you're using a module loader, everything you do is already in its own scope.
It's not constructive to call it a "cop out" to accurately model the behavior of an existing system. What code would you propose we emit for an AMD-targeting program?
The namespace should remain intact, that's all I'm saying. I don't see any reason why it shouldn't. The isolation is now performed very rudimentary on files, instead of intelligently being done on logical groupings.
@MoonStorm I sympathize with your feelings regarding modules, but this is _not_ a failure on the part of the TypeScript team, it is rather a direct consequence of the module specification.
The ECMAScript module specification defines physical modules not logical ones. While this has certain advantages, it's arguably a lower level of abstraction than what could be achieved through a logical module format. However by deviating from the specification, TypeScript would set itself up for long-term compatibility concerns.
Thanks for that @aluanhaddad . The situation is much more clear now.
So what's the solution then? Keep everything in one TS file? Have one module per TS file? No thank you. It seems that the only common sense proposition for medium to large scale projects would be to code in a module-less manner and mash everything up at build time, however in this case the entire module support in Typescript can be thrown out the window. What is the general consensus on the matter?
The recommendation would be to code in modules and use a module bundler, like webpack, browserify or r.js for your output.
@MoonStorm the general consensus is to go ahead and use ES Modules, and to explicitly import every construct from every file where needed. Something many use is an organizational convention where groups of modules, that is files, are re-exported by a co-located file generally named index.ts. Often this file itself is dozens of lines long.
That said, if namespaces are working well for you, you can keep using them and you can still work with modular libraries via UMD style declarations and UMD bundles.
That said moving to ES Modules is a good idea because that's where everything seems to be headed and the support will be there.
Thought I'd chime in here, because it was just last week that I was complaining about this.
It is super unintuitive to go from using namespaces to using file modules. There's something inherently jarring about having individual files "knowing" about other individual files, physically (without additional work). I think the disappointment as far as being a TypeScript consumer goes is that there wasn't some whizbang magic solution that preserved the behavior of namespaces in TS files and completely hid the notion that one potential implementation of a namespaced system is by using window level globals.
From my POV, TS should be smart enough to allow the conveniences of namespace syntax while still, behind the scenes, following modern module loading patterns. The fact that it doesn't makes me think that there should be big red tape everywhere we mention using namespaces saying "Absolutely do not do this, you will regret it in 1-12 months".
What we have seen working with teams to migrate to modules that most of the time is about the logic and figuring out what is your dependency tree, more than actually switching to the module syntax/module loader.
when using namespace, all your code is in one place, and you have everything can access everything, once the initial load is done.
once you move to modules you need to answer the question, what is a module, what components can be loaded by themselves, and what components can not exist without another, and thus should be loaded together.
Sadly these are not things that the compiler can just know. it does not know if all declarations in a file should transition to a module because they are logical entity that need to live together, or they were placed in this file because it was convenient when this code was written. it does not know if a namespace should be split into two or modules, because the original design did not account for different load times or not.
The main source of frustration is that modules and namespaces are eerily similar in syntax to modules, yet they are completely different beasts; developers usually think the transition between these two constructs can not be that big, yet it is.
Most helpful comment
This needs to be re-designed. If later on an import is required into a file that originally had no imports, that would create a ripple effect throughout the entire code base.