TypeScript: TypeScript paths config doesn't work with leading slashes.
TypeScript Version: 2.1.1 / nightly (2.2.0-dev.201xxxxx)
2.1.5
Code
app.ts
import Foo from '/common/Foo' console.log(new Foo)
tsconfig.json
{ "compilerOptions": { "paths": { "/common/*": ["../../common/*"] } } }
Filesystem:
website/ common/ Foo.js somewhere/ project/ tsconfig.js app.js
Expected behavior:
tsc
should be able to recognize that when it sees a dependency like /common/Foo
it should look for website/common/Foo.js
in the filesystem.
Actual behavior:
It can’t.
** More details **
I can get the following to successfully resolve files, by simply removing the leading slashes:
app.ts
import Foo from 'common/Foo' console.log(new Foo)
tsconfig.json
{ "compilerOptions": { "paths": { "common/*": ["../../common/*"] } } }
Filesystem:
website/ common/ Foo.js somewhere/ project/ tsconfig.js app.js
In this case, however, the output module contains something like
output.js
define(['common/Foo'], function(Foo) { /*...*/ })
But this is problematic, because if baseUrl
in RequireJS config is set,
require.config({baseUrl: '/some/place'})
then RequireJS will look for the module at example.com/some/place/common/Foo.js
which doesn’t exist. I need it to look for the dependency at example.com/common/Foo.js
, f.e. TypeScript would output the following including the leading slash:
output.js
define(['/common/Foo'], function(Foo) { /*...*/ })
It would be great if TypeScript could support this case, then the output can still have an absolute path and work as expected.
Unfortunately, RequireJS doesn’t support map configs like the following:
require.config({
baseUrl: '/some/place',
map: {
common: '../../common'
}
})
I think solving this in TypeScript is the best options because then it can be taken advantage of in other environments besides RequireJS.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 21
- Comments: 53 (20 by maintainers)
Commits related to this issue
- match leading slash imports with path mappings - fixes #13730 — committed to EECOLOR/TypeScript by EECOLOR 6 years ago
- path mappings now supports rooted disk paths and urls - fixes #13730 — committed to EECOLOR/TypeScript by EECOLOR 6 years ago
- path mappings now supports rooted disk paths and urls - fixes #13730 — committed to EECOLOR/TypeScript by EECOLOR 6 years ago
- path mappings now supports rooted disk paths and urls - fixes #13730 — committed to EECOLOR/TypeScript by EECOLOR 6 years ago
- path mappings now supports rooted disk paths and urls - fixes #13730 — committed to EECOLOR/TypeScript by EECOLOR 6 years ago
- path mappings now supports rooted disk paths and urls - fixes #13730 — committed to EECOLOR/TypeScript by EECOLOR 6 years ago
- Merge pull request #27980 from EECOLOR/leading-slash-imports match leading slash imports with path mappings - fixes #13730 — committed to microsoft/TypeScript by sheetalkamat 6 years ago
It makes me a bit sad that there has been no response from maintainers on this issue that affects a large part of the community. Do not mistake my words, there is no judgement in them.
The hard part for me personally is that I understand it. Maintaining a popular library is tough, with a small group of people you are trying manage thousands of interactions. Just look at the amount of issues and pull requests in this repository, that’s hard to keep track of.
It would be great if there was a way to sort issues by some sort of value/effort/impact ratio. I think this issue has the potential to be high on that list.
Anyway, if anyone reading this has contacts with any of the maintainers, please ask them to take a look at this issue. The only thing we want to add is the ability to add aliases that start with a slash. No default behavior has to change and it allows us to:
/
/
as the root of our projectWhile you are of course technically correct we could ask ‘What does root mean?’. In web applications this means the web root. There are exactly 0 use cases where I want to include anything from the root of my system, my build server or my production server. One could even argue that it’s unsafe to allow that.
In any case, to me it makes much more sense that
/
refers to the root of the application (for example./src/
). I however understand that for some other people (like the meteor crew)/
should mean the directory that containsimports/
.I would recommend you to either allow for extensions to influence the resolving process (an example for webpack and an example for eslint) or allow the
paths
setting to contain absolute paths:The default behavior can remain the same and from a naive perspective this change does not seem to involve much as testing for an absolute path is rather easy:
path.startsWith('/')
.@mhegazy
Hello Mohamed, you don’t have to pick, you can let the end user pick by giving the user a configurable option. Then everyone will be happy doing it their own way.
FYI, this issue prevents VSCode from working with native web browser module loaders. Browsers don’t support named imports, only relative paths starting with
.
or absolute paths relative to the web server’s root starting with/
. In a web browser not using afile:
URL,import "/foo.js"
doesn’t attempt to access the root of the filesystem.There should at least be a way to make this work for javascript. I’m trying to get vscode to understand my .js files that are written for the browser. Browsers can import from absolute paths, but the path is obviously different in the url than it is on my disk.
I have not heard any convincing arguments to not put this in.
I am willing to dive in and create a pull request but I would need some confirmation from the maintainers before I start working on it. TypeScript is a new codebase for me and I never typed anything in TypeScript. So it will take some effort to get to know the conventions, setup the test environment, etc. The investment in time would be too large to just add it and later discover that the change was rejected.
I had a peek at the code (at least one place that the configuration was used) and it looks very readable. There is quite some indirection and here some
console.log
or breakpoints would be needed to find out how it is used.Anyway, do the maintainers want to add this feature? And if so, would accepting the following form be ok?
@EECOLOR You have my support. That seems like the most general solution, not just for Meteor.
@nexsodev It has been resolved: https://github.com/microsoft/TypeScript/pull/27980
Thanks @EECOLOR and the team for all the work you put into this!
Regarding the “In Discussion” tag: This issue is a blocker for using VSCode with native EcmaScript modules (w/o RequireJS, Webpack & Co). It blocks us from finally moving to loader-less devel setup.
PS Ideally it would be also fixed for dynamic imports.
This seems to go against the design goals of TypeScript because it introduces an opinion about import paths should be interpreted which is clearly not the same across all Javascript frameworks and platforms.
Bare node interprets it this way, sure, but many frameworks including the popular Meteor framework and also users of babel support mapping the leading slash to mean the project root not filesystem root.
Let’s face it, importing a file from the filesystem root is about as useful as a caps lock key and we know many people remap that key as well.
And not that I think you should support everything that Flow does, but they also support mapping the leading slash to something else: https://www.npmjs.com/package/babel-plugin-root-import#dont-let-flow-be-confused
Here’s some other examples of platforms that use the leading slash to mean something else: https://www.npmjs.com/package/babel-root-slash-import
If you can’t tell I REALLY want to use TypeScript on this project but this is a show-stopper. Thanks for considering this.
@andy-ms @DanielRosenwasser @ahejlsberg I got your names from the commit history in master.
I am willing to attempt a pull request for this issue, but as I mentioned in this comment I need a maintainer to sign off on the idea.
Are you the people who should sign off on this? Or should I contact someone else?
I’m also having this problem when attempting to migrate my Meteor application to use TypeScript.
I have code like:
Where Meteor maps
/imports/logging
to<srcdir>/imports/logging.js
Meteor doesn’t use the RequireJS runtime so I don’t have the ability to workaround like this.
My ideal would be to able to re-configure the root to my liking in
tsconfig.json
, ala:"absoluteRootPath": "./"
@mhegazy that’s not compatible with Meteor JS which is a VERY popular Javascript application framework. (currently 38,469 stars on their GitHub Repo) https://github.com/meteor/meteor
all that would be required to solve this is a way to override the absolute path behavior for frameworks that desire it. The default could remain but just a flag as I described in my previous comment would work great.
@Guema as far as I can tell, the code does not use glob to resolve anything. The syntax here is typescript specific and the
*
is used to bind the parts together. Having{ "paths": { "/*": "./src/*" } }
is in my opinion in no way confusing.And you’re free to keep that. We just want to add an alias restricting that behavior.
I value your input. Whether we go with an
alias
orresolveRootPath
configuration setting totally depends on what the typescript teams deems the best solution for their library.Best point so far IMO. even for nodejs code, server code, there is no real sence to use root directory. perhaps, it can be more understandable if you code an Electron.js (or Electron.js like tech) desktop app, maybe, but it is quite a special case…
The problem is, that the actual “NO WAY TO HACK” is pretty annoying, to me, at least, as it prevent plenty of framework using this syntax to be intellisence-compatible, and im not able to hack it… Im currently using meteor, and it is quite laborious, especially when coding large apps with great amount of data model. Intellisence is really useful to get instantly in the code, get desciptions on the go, and correct eventual spelling problem without having to read all files again.
I suggest please to at least add a a js/tsconfig flag, allowing to compute initial “/” as app path instead of system root for intellisence, as it is not possible at all to hack it afterward, as glob does not interpret “/” as any other character.
Hi EECOLOR, I just try this feature in a brand new project created with nest-cli. However it seems not working as expected: check the detail
I was wondering if you could help me with this,
Thank you so much
Leading slash refers to the root directory, so this is an absolute path. path mapping does not work on absolute or relative paths.
still an issue
@red-meadow I should indeed be reported as separate issue. I don’t think I’m qualified to help with this issue. A quick search on Github let me to: https://github.com/microsoft/TypeScript/blob/master/src/services/getEditsForFileRename.ts
That code is used throughout the code base. From a glance it seems that
paths
(aliases) are not taken into account when determining the target rename.If this feature would be added it would probably be something like
preferPathsAliases
or something. This however is probably not preferred when dealing with ‘child’ directories (from./a/a.js
to./a/b.js
). On top of that it will probably have performance implications.In any case, I would create a separate issue for it and see what direction the Typescript core team would want to go.
@davismj Currently on Windows, the leading slash “/” is resolved as your system disk. Basically “C:”, not system32 (i don’t know anymore if your system can be other than C:)
As far i understand, extrapolating from what i read and @mhegazy said :
Resolving leading slash as system root is as far as i know a Linux/Unix norm that is currently being gradually adopted on multiple Microsoft techs (PowerShell, for exemple, but i suppose TS too) allowing more cross-platform consistency for scripts and other things.
As VsCode is a multi-language editor, i suppose path resolve is system-driven by default, because there is no webroot notion in a Py or Ruby app for exemple.
At the same time, Es6/7/8/9/2015/2016/2017 (idk witch one exactly) decided that “/” could be a cool way to resolve root es6 imports as an Nodejs App root or WebRoot depending where you build. (but seems that there is multiple norms depending on frameworks)
TypeScript is a language you want to use for server and/or client and/or prototypes/scripts, so in some case, you want to access file-system with absolute paths (“/”) too AND because it is cross platform, i suppose file-system access must be normalized too.
My speculation is that Intelliscence and/or TypeScript are being in the middle of 2 (maybe more) norms collision, making things a bit more complicated than it seems in a design perspective. But i could be wrong.
(Just expecting i didn’t said big mistakes)
Having the same issue with meteor and typescript… Just need to be able to map the “/” to the root of my project. Right now I have to use
const Utilities = require("/imports/Utilities").default;
and I don’t get any intellisense. It seems to me like allowing a person to map “/” to any path they like is the easiest option. But maybe there is a better one out there. Regardless, there are a lot of people who want to use Meteor & typescript, and I think supporting Meteor would help the typescript project gain even more popularity.