-
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
Support looking for modules under node_modules when importing #247
Comments
[moved to typescript.main in package.json in the issue description above] |
👍 other example. ./test/index.ts
./main.ts
|
[moved to typescript.definition in package.json in the issue description above] |
One solution would be to solve it with better tooling. E.g. |
FYI; I'm actually testing something similar to this in TSD; a way to expose & link definitions that are bundled in the npm (or bower) packages. It's in my dev version for 0.6, and it works by adding a
Then you can run a command on TSD, currently |
@Bartvds That's pretty nice. Could be the first step for having .d.ts in npm packages. I like the package.json structure with "definition" in "typescript", it's a lot more organized. If TypeScript compiler itself could read it automatically, would be very cool. |
Tagging this for discussion -- smarter external module resolution is something we need to talk about to understand the various scenarios here. This was brought up previously and we made a few tweaks in 1.0. |
Also discuss #207 - looking under 'index' |
👍 @chanon |
Yep, the issue is immensely important even for browsers - lots of projects use browserify/packify and therefore node-compatible directory layouts |
👍 There's been some work already in this area back in the codeplex repo, one pull request by leebyron and one by kayahr. I've been meaning to try and port one of them to the new repository, but it seems the related code has been re-arranged a lot. |
I have written a proposal for how to add this to the TypeScript compiler. This also includes looking in the |
Looks sensible. Will this cover modules with clashing type dependencies? I mean if an app imports A and B, and B is also dependent on A. It's easy to fall into duplicate type errors if there are two copies of the external declarations. |
It shouldn't, they should resolve to different external module names so declare identically named independent types in different modules. The structural type checking should then allow the different modules to interact without issues. That's one of the major issues with the current |
@joewood also there will be troubles between different versions of A
|
interested to hear solutions to the same. TypeScript has a |
Even if the versions match, at the moment I see issues with two different, but matching ambient declaration files causing duplicate symbol errors. The locally defined |
@joewood Yep, that's what I hope will be fixed in the majority of cases by changing |
👍 |
👍 |
I've done an initial implementation of my proposal along with creating an example set of modules to show that all the different ways to make a module will work. Including using different versions of the same library in different sub-modules. |
👍 |
They can:
|
@bgrieder I'm referring to the ES6 import syntax. |
(that is is you are using commonjs), if not, use the
|
I think the point being made is that one of TypeScript's goals is that valid JS should be valid TS. For the ES6 module syntax, TS should compile this with or without the presence of type declarations. Without type declarations an I totally agree with that. |
@joe Wood 👍
|
FWIW this behaviour (expecting all 3rd party libraries to be typed ahead of time) is what is causing me to use Flow over TypeScript. While TypeScript has IDE support, expecting everything to be typed ahead of time isn't really reasonable, especially when there are plenty of libraries out there that:
I'd rather not have to fight something that's meant to be aiding my development. |
@danpantry, why not just declare your lib entry point as any, and the compiler will be content with that: declare var $: any; |
That's a workaround. But I think it would be a good idea for TypeScript to respect the ES6 module code and fallback gracefully. I can't see a good reason why an import statement can't fallback to |
I'd prefer the compiler to fail early and loudly (the current behavior), rather than allow runtime issues to creep in unnoticed. I'd prefer to explicitly have a |
Why not just allow the ES6 import syntax when no typings are available an issue a simple compiler warning that the import has resolved to
|
In any case, the compiler currently claims that it can't find the module, when in actual fact it's just refusing to import the module without type definition. That's not really helpful, is it? |
^^^ This a thousand times. There was no indication that I was doing something wrong when I first ran into this issue. It took some long hard Googling to finally figure out what was up (incidentally I think this issue is one of the only findable places that documents it). It's so unnecessary. And with Angular 2 bringing TypeScript more into the mainstream I can only imagine how many Stack Overflow questions will come from this behavior. |
Very much agree with the poor error handling description and just make it import as any! |
@sccolbert I agree there should be a notification but I'm not sure it should be a failure - a warning instead, perhap |
I agree with @mhegazy and @sccolbert. I'd much prefer our production build scripts (i.e. CI server) to complain loudly if something is amiss. |
Hi guys, |
@devel-pa, the errors are meant to tell you that the compiler has no idea what your import is. any subsequent use of the import can not be checked. Switching off the errors does not solve any issues. it just pushes these "unknowns" silently throughout your system. without type information, the compiler can not warn you on what is safe and what is not. and that is the whole point of TypeScript :) As for generated JS. none of the TS type errors stop your output from being generated. if you do not care about the type errors, just ignore them all. the compiler still generates your matching .js files. The solution for missing definitions is to declare them. you do not have to have the full shape of the module declared, but just the name. This allows the compiler to know that there is a module "myLibrary", it can warn you for typos in module names, and more importantly, no other modules would go unchecked. declare module "myLibrary" {
var a: any;
export = a;
} as outlined in #6615, TypeScript should support a shorter form of this soon. |
I think the issue is pain this causes for onboarding projects. I think this problem is analogous to implicit any. Right now these imports are essentially implicit void. Sure, the errors can be ignored, but that causes a lot of noise and goes against the philosophy of gradual typing and valid JS is valid TS. I can understand the confusion here for people new to TS. If they've actively used ES6 module syntax in JS, why doesn't it just work in TS? What's special about |
implicit-any errors are on variable declarations without a type. but using an undeclared variable is still an error today. For jquery, you still need on any rate, #6615 should support adding |
@mhegazy I understand your reasoning but I really have a problem with this rationale Basically, you are telling us to design a "placeholder" module definition, and the problem will go away. The situation is even worse with typed modules (the ones with the I understand these placeholders cannot be prevented, but I would much prefer that, at least, they are not encouraged. (as a side not, as stated on the typescriptlang.org home page, Typescript is a 'superset' of Javascript, and IMHO any valid ES6 syntax should just be swallowed as is) |
Workarounds and hiding the garbage under the carpet are for me the worst that can happen (beside ES6 super). |
what about importing modules from JSPM directory instead of node_modules? edit: i've found an existing ticket -> #6012 |
I just ran into an issue with Node module resolution, when using SystemJS to load a directory: Apparently, while Node (and therefore TypeScript) understands that the path is actually a directory and therefore loads This is also true of node modules that have a index.ts/js entry point or even use the package.json What is the appropriate solution for this? |
JSPM automatic module resolution is not currently supported. this is tracked by #6012. The recommendation is to use path mapping module resolution support, see https://github.com/Microsoft/TypeScript-Handbook/blob/release-2.0/pages/Module%20Resolution.md#path-mapping |
The above instructions are a start, but some people may need to do something additional... You may have to add More infoI was building with gulp, and had TypeScriptCompileBlocked in .nsproj. To fix issues in debugging breakpoints in VS 15 Preview 5 (I was getting "frame not in module" error) and issues I was having with intellisense I had to add to .njsproj . That directory was already there when I imported the project, but was set to git-ignore. That is my theory on why Visual Studio ignored it (perhaps it should have an automatic exception for node_modules?) Beyond both debugging and intellisense working, I also stopped seeing intellisense errors beyond the same exact errors I saw from gulp while it built, which is expected. |
Update 5 November 2015
The functionality requested below is currently implemented in typescript since at least 1.8 with one main difference:
Instead of having
typescript.main
andtypescript.definition
properties, there is only onetypings
property which you can point to either ad.ts
file or a normal.ts
file.If you're developing a module to just use locally, you can have the
typings
point to a.ts
file, but if you plan to publish the module, it is recommended to have it point to ad.ts
file. This is because you don't want your module consumers to recompile your module files, just consume its typings.I have setup an example of using this here:
https://github.com/chanon/typescript_module_example
There is a documentation page here that has more information:
http://www.typescriptlang.org/docs/handbook/typings-for-npm-packages.html
Thank you TypeScript devs and all contributors.
Original issue / feature request follows
Motivation
In TypeScript it is a lot harder to re-use typescript modules compared to re-using npm modules in JavaScript.
It would be beneficial if the typescript compiler is smart enough to look in node_modules folders and package.json files.
The reason is so that npm module developers that use TypeScript might be able to start writing and distributing modules through npm itself. TypeScript would be able to piggyback on npm's infrastructure and wide support.
Example for node_modules
If we had:
And in index.ts we had:
in myApp.ts:
So basically, the compiler is smart enough to find the module in node_modules and it automatically uses the typescript version (index.ts).
Then when the code is compiled to JavaScript, it naturally uses the JavaScript version.
Importing Folders as Modules
A more basic case is supporting Node.js's popular rule of http://nodejs.org/api/modules.html#modules_folders_as_modules as suggested by @vvakame below and in the closed (semi-duplicate) #207 issue.
typescript.main in package.json
There could be an addition to package.json files to specify where the main .ts file of a TypeScript npm module is. This would be similar to the
main
key that specifies where the main JavaScript / .js file is but for TypeScript instead.Eg package.json for an npm module named "myModule" located at
node_modules/myModule/package.json
In this example
node_modules/myModule/src/index.ts
would be the main TypeScript file and doing animport myModule = require("myModule");
would import thenode_modules/myModule/src/index.ts
file.For a JavaScript coder writing
var myModule = require("myModule");
in a JavaScript file, the require would load thenode_modules/myModule/dist/index.js
file as usual.As can be seen in this example, the TypeScript src is in the
node_modules/module-name/src
folder and the compiled JS files would be innode_modules/module-name/dist
.Something like this could be a (semi) standard for TypeScript npm modules so that the TypeScript source is cleanly separated from the compiled JavaScript output.
A more basic case as suggested by @vvakame below is supporting the popular Node.js rule of http://nodejs.org/api/modules.html#modules_folders_as_module
typescript.definition in package.json
Another possible key for package.json for non-TypeScript (plain JavaScript) npm modules could be
typescript.definition
. This would point to a .d.ts file that defines the module for TypeScript users of the npm module.So that an
import $ = require('jquery');
would automatically read a
jquery.d.ts
file defined in thetypescript.definition
key in jQuery's package.json and make$
the correct type.Example format:
(This format is already used by tsd as @Bartvds explains below.)
Then us TypeScript coders would just have to try to get as many non-TypeScript npm module maintainers to merge our pull requests that have our .d.ts files and package.json
typescript.definition
keys.If we succeed with that, then TypeScript coders' life would be bliss ... no more separate managing of DefinitelyTyped .d.ts files. Just npm install and you get your TypeScript definitions too! Automatically and up-to-date with the module version installed.
List of Benefits
What we get from all of this is
typescript.definition
key addition. This allows .d.ts definition files to be packaged together with the npm module so that updating an npm module will automatically update its .d.ts definition file. This removes the need to update .d.ts files manually.typescript.definition
is simpler because it is simply animport moduleName = require("moduleName")
statement with no need for a separate///<reference ...
typescript.definition
should also allow the use of different versions of the module in the same code base without type names clashing.Detailed Proposal
@Nemo157 has written a very detailed proposal for how all of this should work at:
Proposed TypeScript Require Resolution Semantics
https://gist.github.com/Nemo157/f20064a282ee620f3877
An addition in the proposal is the usage of
/typings
folders which can hold definition files that can be automatically managed by tools such astsd
for JavaScript npm modules that won't include definition files in their repositories.Final Supporting Facts
Since TypeScript compiles to JavaScript which runs mainly in two places: node.js and in browsers, supporting node_modules is beneficial to both places (practically all of where TypeScript is used) because of npm and Browserify/Webpack.
ie. there is no reason to come up with a different scheme when node_modules is what all TypeScript users use already for maybe 75%-100% of all their JavaScript code. (Taking out 25% for maybe RequireJS users.)
Footnotes
[1] - BTW I see there is a NuGet package manager (?) from Microsoft that can distribute typescript modules (?), but coming from a node.js focused (non .NET focused) background, I don't see NuGet becoming widely used outside of Microsoft focused shops, especially as npm is the standard for node.js and is a leading standard for client side JavaScript too. If I didn't use TypeScript I would have never heard of NuGet. The average node.js / client side JavaScript coder would probably prefer using npm, the same tool they use already rather than having to use something Microsoft specific such as NuGet. (I don't actually know a thing about NuGet so what I'm saying here might not actually matter.)
The text was updated successfully, but these errors were encountered: