-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use external module in internal modules #557
Comments
look at #17 - does is about the same? |
Well this is more of a question than a feature request or a bug report. I'm simply trying to understand and discuss it. Regarding #17 , that still pertains to external modules. I would like to avoid having to make my internal modules external. Hence the question of whether that's feasible in that context, and if not, what the best workaround not involving a future release would be. |
This .d.ts file was written in the good "internal/external" pattern whereby you can consume it simply by referencing the .d.ts file and adding this line of code somewhere in your file: declare var _: UnderscoreStringStatic; Closing, but feel free to post follow-up questions. |
Even if it's old, the title is exactly what i'm looking for. I look at #17 and i'm not sure it's the same issue. And as there is no clear answer, I'll try to explain the question clearly. I want have an app.tsx which looks like this : /// <reference path="../../../typings/tsd/react/react.d.ts" />
import * as React from "react";
class App extends React.Component<React.Props<App>, AppState> {
...
}
class Foo extends React.Component<React.Props<Foo>, any> {
...
} I want to organise the code, mainly by spliting the file and get /// <reference path="../../../typings/tsd/react/react.d.ts" />
import * as React from "react";
module Other {
export class Foo extends React.Component<React.Props<Foo>, any> {
...
}
} Now, the /// <reference path="../../../typings/tsd/react/react.d.ts" />
/// <reference path="Foo.tsx" />
import * as React from "react";
class App extends React.Component<React.Props<App>, AppState> {
...
var t:Other.Foo; // <= not recognized
....
} As I understand things, Other.Foo don't work because in Foo.tsx, there is an import of an external module. So going back to the title of the question : How can I use external module in internal modules ? |
Change |
Great ! thanks @weswigham . |
Ho no... Sorry, it still not good. It works for one file only. As soon as I have a second file and I want it to contribute to the same module, I can't use |
Namespace merging is not a feature you can use with external modules. Instead of using namespaces to create a group of methods, use a file instead. For example, assume I have a foo.ts and a bar.ts: export function foo() {} export function bar() {} If I want to access both of those through one object, I can create a third file, api.ts: export * from "./foo"
export * from "./bar" And now I can Namespaces I find aren't actually terribly useful with external modules, except for singletons and file-internal organization. |
@weswigham Sure, and then you pollute the global scope by adding a gazilion different exports to it. |
How do external modules "pollute" anything? You can't even easily declare globals when using external modules, because everything gets module-scoped. |
I thought you meant:
In the first case, isn't foo living in the window object? In either case; what this boils down to is something very simple: If you want to use separate your code using internal modules, then you effectively can't use third party libraries. Take a look at: http://stackoverflow.com/questions/35582275/using-a-node-library-within-a-typescript-internal-module Referencing a gazilion different files via a relative path is ugly. |
The first case does not put anything on the window object - it generates a module closure (depending on the module format) and adds that function to the exports of that closure. That stack overflow post is shallow in its analysis (and is also an unanswered question) - any namespace structure can be replicated with external modules - look at tslint as a great example both of how to migrate from namespaces to external modules (see the code before v3, then after v3) and of how you can use external modules to layer APIs in this way to imitate namespace structure. While you can reference everything directly, as done in that SO post, that can be indicative of poor API design, as that's akin to reaching into the "internal" API of every module you use, rather than organizing things into groups (API layers), then importing from that group (API). When done correctly, you should be able to pull in most of what a given file needs via a single import. Angular is actually structured very well internally, in this regard. |
Thank you for your suggestions, but you are basically saying:
I think you are right 95% of the time. In my specific use case, I have typescript files (Models) that are going to be generated by an external tool. Rather than using imports for cross-dependencies between model files, a "namespace Models" before every class file would have been perfect and reduced code-generation complexity. Converting to external modules would not solve the problem, because external modules do not support namespace merging. So I cannot, say, have something like:
I have to now import "Address" manually in UserModel. Is there any alternative? |
import * as Models from "./index";
export class UserModel extends Models.Model {
addresses : myListLib.List<Models.AddressModel>;
}
import * as Models from "./index";
export class AddressModel extends Models.Model {}
export class Model {}
export * from "./Model";
export * from "./AddressModel";
export * from "./UserModel"; You can also destructure only the members you need out of the import statement, which, IMO, usually makes it more clear what other bits the component depends upon. Using them from another part of your program (assuming these are all in a import * as Models from "./models"; // finds ./models/index.ts under node module resolution
let model = new Models.UserModel(); Let me also clear something up for you which you example make it seem like you may be confusing: |
Probably worth linking this, as usual: http://stackoverflow.com/questions/30357634/how-do-i-use-namespaces-with-typescript-external-modules |
That makes sense. I think the confusion stems from comparing namespaces to C# namespaces (the 'as usual' makes me think I'm not the only one). Intuitively, if you were a C# developer, your brain says, this is the equivalent of using an external DLL/Library (external module) in C#, and the compiler says you cannot use namespaces (internal module) in the same file - why is this limitation in place?!. That said, it is purely my confusion and I should be comparing with Javascript not C#. Thanks for clearing this up! |
Hi,
I don't have a strong background in JavaScript, I have mainly been coding in C#.
I'm starting a client-side application using TypeScript and Angular.js and wish to use the underscore.string library, with its TS definition available on NuGet.
Here is an excerpt of that definition:
Here are my observations and assumptions:
The definition contains
declare module 'underscore.string'
. The quoted name automatically makes it an external module.Had it been
declare module underscoreString
, it would still have been an external module because of its use ofexport =
.If I write
import _ = require('underscore.string')
in the same file as an internal module (but not within the module), that internal module has to become external. Besides an error appears:Cannot compile external modules unless the '--module' flag is provided.
(Which, in a VS project, means having to check either AMD or CommonJS in the project properties)If I try
import _ = require('underscore.string')
within an internal module, that internal module also has to become external, otherwise the following error appears:Import declarations in an internal module cannot reference an external module.
The language specification for v1.0 mentions an ImportDeclaration in section 10.3:
However this only applies to internal modules, which 'underscore.string' is not if my first assumptions are correct.
If I change my internal modules to be external, they won't be open-ended anymore and I will need to name a different module for each of my files.
I do not have difficulty using Angular.js because it was declared as an internal module.
Now, my main question is:
How can I use what appears to be an external module ('underscore.string') in my open-ended internal modules?
If I can't, then my corollary question is:
What is the most convenient way to structure the application without having to declare a new external module for each file? Especially since I would only name those modules after the sole class they contain (I follow C# convention of 1 class = 1 file).
Ideally I would deal with modules as I deal with .NET namespaces, but the way it looks now, I would have to deal with them as if every file were a .NET assembly.
Thanks in advance for any clarification
The text was updated successfully, but these errors were encountered: