You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am trying to use external module within an internal module but Visual Studio won't let me do that.
As soon as I add an import x = require('xxx'); the internal module no longer consider the file to be part of the module and all exports are not referenced by the module anymore.
I have read the Module Documentation but I could not find the scenario of using external modules within an internal module.
As described in my post, I want to create a ViewModel module that will contain all the ViewModels of my application.
The application will use Knockout in order to insure the communication between the Views and the ViewModel and I therefore need to import the knockout module.
// HomePageViewModel.ts
import ko = require('knockout'); // When adding this line I can no longer access HomePageViewModel from the internal ViewModels module
module ViewModels {
export class HomePageViewModel {
constructor() {
console.log('Creating HomePageViewModel');
}
}
}
// ViewModelFactories.ts
module OtherModule {
export class ViewModelFactories {
public static CreateHomePageViewModel(): ViewModels.HomePageViewModel {
return new ViewModels.HomePageViewModel();
}
}
}
When importing the external module knockout, the internal module no longer exports the HomePageViewModel class.
I think the question was decently answered on StackOverflow. You can't be "half" internal module and "half" external module -- this is just a fact of how AMD module loading works. The solution is to either make your application 100% internal modules or 100% external modules.
I've struggled with this problem a lot myself, which is why I don't use ES6 modules. Maybe it makes more sense for a Node application. I'd love a better solution though.
Actually the TypeScript compiler itself is "half" internal module and "half" external module. You are loading AMD modules in sys.ts while not being an AMD module. As there is no solution available currently, the TypeScript compiler itself doesn't use type checking here and falls back to any.
I think it should be possible to either use the import statement inside non AMD modules like in the example above or at least reference the typings of named modules like this:
jedmao
I have the same problem when using mongoose within my modules ... i can import mongoose and reference the it with the definition files of definitelytyped, then mongoose types are resolved correctly but my internal references cannot be resolved anymore. so the solution for this problem is to use only external module definitions ?
Ryan Cavanaugh (@RyanCavanaugh) For instantiated modules, this is true. But the compiler complains in non-instantiated modules, too, which means it is impossible to describe global types in an ambient declaration if those global types refer to a type that comes from some other external module:
// in foo/foo.d.ts/// <reference path="../external/external.d.ts" />declare module foo{// TS Error: Import declarations in an internal module cannot reference an external module.importrequest= require('external/request');interfaceRequestErrorextendsError{// …/** * The response object for the request. */response: request.IResponse;}// …}declare module 'foo/Bar'{// …classBar{error: foo.RequestError;// …}export=Bar;}// …
The internal module foo could be written as an external module, but given the way other declaration files are authored, I think that would be considered an anti-pattern at this point.
Colin Snover (@csnover) is it expected that the JavaScript molded by these definitions be accessed as both an internal module (e.g. include the js in a script tag) or required (either using an AMD loader or commonjs)?
one pattern that i have seen is to define all your typeings in an internal module, and then have an external module to expose them as well:
The main problem is that external modules and internal modules are really different, the shared syntax does not help here obviously. The compiler can understand external modules consuming internal modules, as they just represent global objects, but it can not understand what the opposite means in absence of a loader system.
Since your code is accessible both as a module, or addition to the global namespace, i assume your dependencies are as well (e.g. 'external/request'), if your dependencies expose an internal module (something along the lines i mentioned above) then that should solve the problem.
We have the same problem with typescript definitions, and the way we worked around it is by using two files one internal and one external, though we have no dependencies that we expose in the .d.ts.
Colin Snover (@csnover) is it expected that the JavaScript molded by these definitions be accessed as both an internal module (e.g. include the js in a script tag) or required (either using an AMD loader or commonjs)?
if your dependencies expose an internal module (something along the lines i mentioned above) then that should solve the problem.
Unfortunately I don’t think it’s safe to presume that the way the external dependencies are structured could be changed, as they are, well, external.
In this concrete example above, the dependencies come from well-structured modular code, and it would be wrong for that upstream project to move all these interfaces out of external modules.
(P.S. Sorry for not linking to the real examples before, they weren’t done at the time I wrote the post.)
What I understand is there no option to create standalone node.js application consisting of internal modules? As using node.js requires importing external dependencies (like streams, events etc.) hence every module using these becomes external module. It's even more restrictive, extending this policy on non-module TS files, so that any file containing require can't be used as <reference>.
Correct me if I'm wrong, but this makes internal modules completely useless, and the only hope is in Suggestion: multi-file external modules #17.
As a convenience for generic interfaces that are used in multiple places across an entire package but don’t emit code. The alternative is to create some a separate interfaces/typedefs module, which could be OK (and would improve portability), but just runs against how these things are typically modelled right now in DefinitelyTyped. I’m mostly OK moving to that model if that’s what everyone thinks is best, but I’m sure some people will complain about all the extra typing they have to do whenever they want to use one of these generic interfaces (most developers are incredibly lazy).
i see. thanks for the explanation. The problem is internal modules should have been called namespaces :). i do not think the two really mesh well just because of dependencies in external modules, and the open-ended nature of internal modules.
Activity
RyanCavanaugh commentedon Oct 17, 2014
I think the question was decently answered on StackOverflow. You can't be "half" internal module and "half" external module -- this is just a fact of how AMD module loading works. The solution is to either make your application 100% internal modules or 100% external modules.
jednano commentedon Oct 17, 2014
I've struggled with this problem a lot myself, which is why I don't use ES6 modules. Maybe it makes more sense for a Node application. I'd love a better solution though.
sebastian-lenz commentedon Oct 26, 2014
Actually the TypeScript compiler itself is "half" internal module and "half" external module. You are loading AMD modules in sys.ts while not being an AMD module. As there is no solution available currently, the TypeScript compiler itself doesn't use type checking here and falls back to
any.I think it should be possible to either use the import statement inside non AMD modules like in the example above or at least reference the typings of named modules like this:
jednano commentedon Oct 26, 2014
Sebastian Lenz (@sebastian-lenz) if you reference the DefinitelyTyped knockout.d.ts file at the top, you can:
alex6o commentedon Dec 21, 2014
jedmao
I have the same problem when using mongoose within my modules ... i can import mongoose and reference the it with the definition files of definitelytyped, then mongoose types are resolved correctly but my internal references cannot be resolved anymore. so the solution for this problem is to use only external module definitions ?
csnover commentedon Mar 8, 2015
Ryan Cavanaugh (@RyanCavanaugh) For instantiated modules, this is true. But the compiler complains in non-instantiated modules, too, which means it is impossible to describe global types in an ambient declaration if those global types refer to a type that comes from some other external module:
The internal module
foocould be written as an external module, but given the way other declaration files are authored, I think that would be considered an anti-pattern at this point.mhegazy commentedon Mar 8, 2015
Colin Snover (@csnover) is it expected that the JavaScript molded by these definitions be accessed as both an internal module (e.g. include the js in a script tag) or required (either using an AMD loader or commonjs)?
one pattern that i have seen is to define all your typeings in an internal module, and then have an external module to expose them as well:
The main problem is that external modules and internal modules are really different, the shared syntax does not help here obviously. The compiler can understand external modules consuming internal modules, as they just represent global objects, but it can not understand what the opposite means in absence of a loader system.
Since your code is accessible both as a module, or addition to the global namespace, i assume your dependencies are as well (e.g. 'external/request'), if your dependencies expose an internal module (something along the lines i mentioned above) then that should solve the problem.
We have the same problem with typescript definitions, and the way we worked around it is by using two files one internal and one external, though we have no dependencies that we expose in the .d.ts.
csnover commentedon Mar 8, 2015
No, always required. The internal type
foois just for the type system, it’s never related to any real code. See https://github.com/theintern/intern/blob/typings/typings/leadfoot/leadfoot.d.ts#L5-L51 for a concrete example.Unfortunately I don’t think it’s safe to presume that the way the external dependencies are structured could be changed, as they are, well, external.
In this concrete example above, the dependencies come from well-structured modular code, and it would be wrong for that upstream project to move all these interfaces out of external modules.
(P.S. Sorry for not linking to the real examples before, they weren’t done at the time I wrote the post.)
marcinporebski commentedon Mar 11, 2015
What I understand is there no option to create standalone node.js application consisting of internal modules? As using node.js requires importing external dependencies (like streams, events etc.) hence every module using these becomes external module. It's even more restrictive, extending this policy on non-module TS files, so that any file containing require can't be used as
<reference>.Correct me if I'm wrong, but this makes internal modules completely useless, and the only hope is in Suggestion: multi-file external modules #17.
mhegazy commentedon Mar 11, 2015
Colin Snover (@csnover) sorry for the late reply. I am a bit confused. so why do you need the internal module for your typings?
csnover commentedon Mar 11, 2015
As a convenience for generic interfaces that are used in multiple places across an entire package but don’t emit code. The alternative is to create some a separate interfaces/typedefs module, which could be OK (and would improve portability), but just runs against how these things are typically modelled right now in DefinitelyTyped. I’m mostly OK moving to that model if that’s what everyone thinks is best, but I’m sure some people will complain about all the extra typing they have to do whenever they want to use one of these generic interfaces (most developers are incredibly lazy).
mhegazy commentedon Mar 11, 2015
i see. thanks for the explanation. The problem is internal modules should have been called namespaces :). i do not think the two really mesh well just because of dependencies in external modules, and the open-ended nature of internal modules.
mhegazy commentedon Jun 12, 2015
I do not think there is more actions here that are not already captured in other issues. please reopen a new issue if this is not the case.