-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Specify (absolute) path for library projects #293
Comments
Seems reasonable. If someone has a precise proposal (https://github.com/Microsoft/TypeScript/wiki/Writing-Good-Design-Proposals) that would be great. |
Without being too formal (yet) I think the compiler flagged version could work (as proposed in the codeplex issue).
config.json contains the absolute paths of the libraries
|
+1 the current compiler does not provide enough configuration. |
I'm thinking if a config.json will be used, should we have it as an individual file just for the path config or would there be other uses for a common config.json that could be fed to the compiler. In which case it would have a content similar to this:
Regarding implementation and usage, I think it'd be pretty straightforward, just substitute the project's path so this:
becomes this:
It only makes sense to use {projectA} as the first characters of the path string although it wouldn't hurt to allow to place it anywhere. What do you think? |
To me this is the only missing peace from TypeScript to be able use it in production. So please do comment on the above! :) |
This is a big one for me. There absolutely must be a way to import references relative to your project's root. |
As a current workaround you can use grunt-ts transforms : https://github.com/grunt-ts/grunt-ts#transforms |
Actually there's absolute path available for references but it's relative to the root of the hard drive which I think is quite unuseful - couldn't it be changed to be relative to the project's root folder ie. the folder you run the compiler in. Eg. if you compile your files like this:
then project root is the folder Main.ts is located in. Nevertheless, even if it did work like this I think there would be a need to use {projectA} like substitutions, because that can work like a symbolic link to a library project. |
Is there anything I can do to help this move forward? |
Is there a reason why the same lookup strategy as the 'require' statement can't be used? A fully qualified path from the root would then work as expected. |
Wow. |
@RyanCavanaugh sent me an answer regarding my questions. This includes tips for implementing if anyone would like to - I didn't have the time to get into it yet. Here's his reply: Additional things we’d like to see in a proposal like this would be:
Tips on implementing, since I think this should be fairly straightforward:
Caveats: Our design backlog is very full right now (lots of ES6 features to figure out), so it will be a while before we have a chance to look at anything lower-level. We also might end up folding this suggestion in to the external module resolution proposal if it makes sense. |
If anyone's working on this, see #1567 for a "motivating example". TL;DR: RequireJS does not play nicely when you try to use relative module paths from various project locations. Currently the only way to get around this is to define every AMD module in a separate definition file, with the aliased AMD paths. For an AMD project of any real size, this is a maintenance nightmare.
I understand the push for more and more features, but I would urge the TypeScript team to take a step back and make sure that existing features are well thought out and documented. I just spent the last week trying to convert a large RequireJS project over to TypeScript. I was disappointed with how many "gotchyas" I ran into when trying to use the TypeScript module system, and how little documentation there was for the problems I experienced. |
@eschwartz I've dropped all desire to use AMD for new projects due to all the config nightmares. Even for non-TypeScript projects its painful. Consider browserify or webpack. |
I've always had a bad feeling about AMD. Internal modules + Uglify is another option. |
@basarat Where were you 2 years ago to tell me that....? Here's the dilemma I see: on the one hand, TypeScript has promoted itself by saying that it's really easy to "make the switch". Building in configuration or whatever to support ReqJS quirks would really help make that case. On the other hand, do we really want to design a language spec around the idiosyncrasies of some non-standard vendor library made in 2010? As much as I might complain about how hard the switch was, as a javascript developer I should know by now that my codebase is going to be obsolete every two years, anyways :) In the end, I think the biggest hurdles I saw as a TS convert were:
Maybe if I have a some time yet over the holidays, I can put together a little walkthrough for converting from ReqJS -> AMD. |
No 😃 I often worry about statements coming out of TypeScript along the lines of "we need to support real-world libraries that follow such and such a pattern" - when most of them are going to be obsolete when ES6 and typed JavaScript takes hold. @eschwartz, you may find some useful information on modules in these old codeplex threads: |
Coming from a Java background, this doesn't look much different than the java compiler dealing with classes and packages. In Java, you define classes in a packages (e.g.: in com.foo.bar.SomeClass) and the compiler finds classes referenced by Java code relative to the classpath: Similarily, a tsc compiler option could be added: --referencePath, and the syntax for a reference could be updated to recognize a path relative to this referencePath using some special character that only has meaning if you use the -referencePath option, maybe '@', or something: So, with: No special configuration files are needed for this. You would just have to tell the compiler the root(s) of your file structure to search for references, and indicate that the path is relative in your tag in your .ts files. |
It is an anti-pattern to put relative paths in source code. When you move or copy code to a different level in the directory hierarchy, it breaks. When you move a library it breaks all source files that reference it. Also, the library path has to be specified somewhere, in order to load the code, so duplicating the paths in the sources violates the DRY principle. I agree with @mconner, this problem has already been solved in C and other compilers where you can specify include paths. However, it generally doesn't require the sources to specify a variable (such as "{projectA}" or character (such as "@"). The source file specifies a partial path, or just the file name, and the compiler finds it. As a workaround I am using a "_references.ts" file and avoiding putting reference paths in other sources. ProposalI would like to propose two properties to the "tsconfig.json" file. "libraries": [
"/libs/projectA/src",
"/libs/projectB/src"
],
"references": [
"/libs/angularjs/angular.d.ts"
] The "libraries" property is similar to @andrewvarga's proposal, but it only defines search paths, not variables for substitution. A source file can reference "/libs/projectA/src/Foo.ts" using: /// <reference path="Foo.ts" /> It should be an error if the reference path does not resolve to a single file. The "references" property works the same as "_references.ts". Having the property in "tsconfig.json" puts all the configuration information together in one place so it is easier to maintain. What the Compiler Has to Do
There is a performance impact because the reference path search needs to be exhaustive, in order to catch ambiguous reference errors. However, the exhaustive search only needs to be done if the developer opts in by specifying a "libraries" property. Also, there are many ways the searching could be optimized, and the results can be cached. There is no impact on generated code, compatibility, or any other features. |
The reason I suggested a special character (e.g.: @) is that without it, the path is ambiguous. Is it from the root (i.e.: relative to one of the specified paths) , or is it relative to the current file. In Java, it is always from the root (or roots, as defined by the classpath), and so no special character is necessary. But to support both existing relative paths and root-level paths, it would be better to be explicit. This also reduces the amount of searching that would be necessary, and eliminates an accidental hit (however unlikely) where the author meant one, but got another. |
FWIW I made a proof of concept of the fact that tooling can make it easier : https://github.com/TypeStrong/atom-typescript#relative-paths it can do even more over time. |
We consider this thing to be outside the scope of tsc, which we generally think of a compiler that does what it needs to and nothing extra. External build systems that understand TypeScript can provide this functionality themselves and provide better flexibility and configurability. If those external tools settle on a good common pattern that everyone likes, or don't come up with anything at all, we can revisit this post-2.0. |
@RyanCavanaugh - I would really like this to be the case, but the problem is that tsc has already taken on the task of converting ES6 style module imports to AMD style imports. Now that that decision is made, we're kind of stuck with supporting the quirks of AMD module loading, one of which is the lack of support for relative import paths. I think the best solution would be for TypeScript to split out the *TypeScript to Javascript compiler" from the the "ES6 module to CommonJS/AMD" compiler. Then we could certainly close this issue as out-of-scope. But if that's not he direction the TS team wants to go, I would like to see better support for AMD. |
@eschwartz We are looking into solving some of these issues in #2338, we expect this to be in TypeScript 1.6; can you take a look at the suggestion and let us know if that solves the issues you are running into with AMD? |
Banging my head against this issue currently. My scenario: Code lives in a 'source' folder that is a sibling of the 'typings' folder (from I'll take a look at the suggested transform suggestions above. |
Turns out if I leave out the |
That is by design. See http://blog.icanmakethiswork.io/2015/02/hey-tsconfigjson-where-have-you-been.html?m=1 for more about not needing reference tags |
it'd be good to have a ~ like .NET .. then at least we could move around files in the directories themselves whilst not having to worry about breaking relative references eg |
I'm moving this issue here from codeplex:
https://typescript.codeplex.com/workitem/1414
This feature would help to use "library projects" in a way that you only have to specify the actual path once (eg. with a compiler flag).
I'd love to see this implemented in the official compiler. I think it's small work and adds huge value.
I can have a try at adding this but I'd value some guidelines on how to edit the compiler and how it would make it's way to be part of the official compiler.
The text was updated successfully, but these errors were encountered: