Typescript: Module path maps are not resolved in emitted code

Created on 12 Sep 2016  Ā·  76Comments  Ā·  Source: microsoft/TypeScript

TypeScript Version: 2.0.2

Code

_tsconfig.json_

{
    "compilerOptions": {
        "target": "ES6",
        "module": "commonjs",
        "baseUrl": ".",
        "paths": {
            "foo/*": ["*"]
        }
    }
}

_app.ts_

import {Foo} from 'foo/utils';
console.log(Foo);

_utils.ts_

export const Foo = 'Foo';

Expected behavior:

% ./node_modules/.bin/tsc && node app.js
Foo

Actual behavior:

% ./node_modules/.bin/tsc && node app.js
module.js:457
    throw err;
    ^

Error: Cannot find module 'foo/utils'
    at Function.Module._resolveFilename (module.js:455:15)
    at Function.Module._load (module.js:403:25)
    at Module.require (module.js:483:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/home/mfischer/src/videmo/tsc-test/app.js:2:17)
    at Module._compile (module.js:556:32)
    at Object.Module._extensions..js (module.js:565:10)
    at Module.load (module.js:473:32)
    at tryModuleLoad (module.js:432:12)
    at Function.Module._load (module.js:424:3)

_app.js_

"use strict";
const utils_1 = require('foo/utils');
console.log(utils_1.Foo);

Typescript is finding the right module, but in the emitted code, the module path is left as-is instead of applying the path aliases from tsconfig.json. Obviously node has no idea where to find the module. I would have expected typescript to resolve the module path and replace it with something that node can resolve.

If this behavior is intended, then how can the path maps be used to solve the relative-import-hell in conjunction with node?

Working as Intended

Most helpful comment

Can someone tell me what the point of this feature is if the pathnames emitted are actually incorrect? That is to say, if the TypeScript compiler is happy with it, but the end result isn't runnable - what's the use case for this feature?

All 76 comments

Do you use some other bundling tool like browserify or webpack on the generated output? or do you expect this to run directly on node?

If this behavior is intended, then how can the path maps be used to solve the relative-import-hell in conjunction with node?

Well and to add context, "paths" is designed for use with loaders that allow remapping, unlike the Node.js require(). The intended behaviour is to allow TypeScript to resolve type information for various module IDs used by various loaders, not to rewrite module IDs. Basically it doesn't do what you thought it did. Nor should it in my opinion, it should only have the capability to mirror the resolution strategies of loaders.

@mhegazy I expected it to work directly with node. It's for a backend application. Is @kitsonk correct in stating that this is working as intended and typescript will not rewrite module paths?

yes, this was the intent - to mitigate the mismatch between runtime and design time experience when module (as it is written by user) can be resolved in runtime but failed to be found by the compiler. At this point compiler always assumes that module id provided by the user is correct and never tries to change it.

All right, thanks. It might be useful to document this better in order to prevent more people from being confused. I now use https://www.npmjs.com/package/module-alias to make it work with node.

Appreciating TS's position, here's a simple solution to the 90% use case for those of us using node, but wanting the convenience of using baseUrl relative require() calls without any fuss.

This solution hooks node's require() call, and resolves requests using the dirname of "main" to mimic baseUrl. It therefore assumes the baseUrl compiler option was also set to the same directory where the source "main.ts" was located.

To use, paste this tiny chunk of code at the top of your "main.ts".

import * as path from 'path'
import * as fs from 'fs'
(function() {
  const CH_PERIOD = 46
  const baseUrl = path.dirname(process['mainModule'].filename)
  const existsCache = {d:0}; delete existsCache.d
  const moduleProto = Object.getPrototypeOf(module)
  const origRequire = moduleProto.require
  moduleProto.require = function(request) {
    let existsPath = existsCache[request]
    if(existsPath === undefined) {
      existsPath = ''
      if(!path.isAbsolute(request) && request.charCodeAt(0) !== CH_PERIOD) {
        const ext = path.extname(request)
        const basedRequest = path.join(baseUrl, ext ? request : request + '.js')
        if(fs.existsSync(basedRequest)) existsPath = basedRequest
        else {
          const basedIndexRequest = path.join(baseUrl, request, 'index.js')
          existsPath = fs.existsSync(basedIndexRequest) ? basedIndexRequest : ''
        }
      }
      existsCache[request] = existsPath
    }
    return origRequire.call(this, existsPath || request)
  }
})()

If you're going to use the module-alias package that mika-fischer mentioned, note that the paths you register to the package shouldn't end in /, and the paths are relative to the path where package.json is (it may be obvious but it's good to get it clear),

So if you have this in your tsconfig file:

"outDir": "./dist",
"baseUrl": ".",
"paths": {
  "foo/*": ["./src"]
}

You have to register this in your package.json:

"_moduleAliases": {
  "foo": "dist"
}

Well and to add context, "paths" is designed for use with loaders that allow remapping, unlike the Node.js require(). The intended behaviour is to allow TypeScript to resolve type information for various module IDs used by various loaders, not to rewrite module IDs. Basically it doesn't do what you thought it did. Nor should it in my opinion, it should only have the capability to mirror the resolution strategies of loaders.

Got here after wasting some time trying to set it up in a big project.
If this behaviour is not going to change the least you could do is to update the documentation before closing this issue.
The official documentation https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping%20docs does not say a thing about having to use "loaders that allow remapping" whatsoever.

install and run "tspath" in your project folder... https://www.npmjs.com/package/tspath

Also you can try "momothepug/tsmodule-alias" to alias path resolution:

https://www.npmjs.com/package/@momothepug/tsmodule-alias

I too managed to get this working with module-alias, with the downside that I have to keep track of my aliases both within tsconfig.json and package.json. Has anyone found a simpler solution?

The solution pointed out by @mattyclarkson also works, but I couldn't find a way of using it side-by-side with ts-node. Any ideas?

Take a look at https://github.com/momoThePug/tsmodule-alias

2018-05-31 15:04 GMT-05:00 edufschmidt notifications@github.com:

I too managed to get this working with module-alias, with the downside
that I have to keep track of my aliases both within tsconfig.json and
package.json. Has anyone found a simpler solution?

The solution pointed out by @mattyclarkson
https://github.com/mattyclarkson also works, but I couldn't find a way
of using it side-by-side with ts-node. Any ideas?

ā€”
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/issues/10866#issuecomment-393662306,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ACKT9JWIkb0Wekz0H_Z3zKXvoE-49EIBks5t4EzkgaJpZM4J6vZQ
.

Thanks @DanyelMorales, this is really handy.

you're welcome! :)

2018-05-31 16:35 GMT-05:00 edufschmidt notifications@github.com:

Thanks @DanyelMorales https://github.com/DanyelMorales, this is really
handy.

ā€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/issues/10866#issuecomment-393688075,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ACKT9GNo30wNv4ZWzSwm_Lv4vesLPI3xks5t4GIzgaJpZM4J6vZQ
.

Can someone tell me what the point of this feature is if the pathnames emitted are actually incorrect? That is to say, if the TypeScript compiler is happy with it, but the end result isn't runnable - what's the use case for this feature?

How should one do relative path mapping for things that are NOT modules, i.e. not imports?

In a node script that reads a certain directory relative to the source file I used to do:

const starterDir = path.resolve(__dirname, './templates/starter')

since typescript compiles the script and writes it to another directory (based on config), __dirname will no longer lead to the above path resolving. What would be a solution to this?

How should one do relative path mapping for things that are NOT modules, i.e. not imports?

That is really "how do I use Node.js and TypeScript question" and much better asked in Gitter.im or StackOverflow.

I love TypeScript but this is insanity.

I don't get it. Even with me knowing little about the TS codebase, this shouldn't be hard to implement. I've just started using a shared project with client and server... why does TS present the paths functionality in the first place, then makes me jump through hoops to actually use it? Why does TS assume that I want to use a bundler/loader with every project I make? I'm trying to use TS to simplify my projects, not tack on more tooling libraries to compensate for a 90% implemented TS feature.

I agree with you. I think, TS was developed for frontend, 'cause webpack
already implements quite well ts alias paths, and with Requirejs is also
the same thing. But for Nodejs projects it's so hard. :(

El jue., 20 de sept. de 2018 02:50, Josh Pike notifications@github.com
escribiĆ³:

I don't get it. Even with me knowing little about the TS codebase, this
shouldn't be hard to implement. I've just started using a shared project
with client and server... why does TS present the paths functionality in
the first place, then makes me jump through hoops to actually use it? Why
does TS assume that I want to use a bundler/loader with every project I
make? I'm trying to use TS to simplify my projects, not tack on more
tooling libraries to compensate for a 90% implemented TS feature.

ā€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/issues/10866#issuecomment-423077950,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ACKT9DD_z4KOHpfwddTomMXujEsza9tQks5uc0jbgaJpZM4J6vZQ
.

+1!

webpack may help me to resolve path maps (or other tool likes babel-plugin-module-resolver) but not declarations (.d.ts).

All paths in declaration are not resolved. And declarations seem unusable.

Ran into this issue as well. Seemed logical that the emitted code would include path mappings. Resorted to module-alias. But +1 for Typescript to optionally provide this functionality.

Can this not just be added as a compiler option? Clearly it's a popular request. Knowing nothing of the workings of the compiler, shouldn't implementing it be super simple? Why force us to jump through hoops elsewhere when it can be so easily solved directly with the TypeScript compiler, where it makes the most sense?

+1

You can compile absolute and path-based TypeScript imports to relative Javascript files using ts-transformer-imports and ttypescript

I've created a compile-time solution where you can continue using tsc. https://github.com/joonhocho/tscpaths

Microsoft/TypeScript#15479 (comment)

I have just been struck with this issue when trying to get vue-cli to output d.ts files where there are lots of import {foo} from "@/some/folder/foo" and the d.ts files outputted dont resolve the alias.

From general searching and looking over this thread and others it looks like the knee jerk reaction is "this isnt a problem for TS to solve" but I would implore the team to change that stance as currently if you use custom path alias (completely valid and recommended approach for complex projects) you simply cannot use generate d.ts files (without a custom 3rd party build process) so I would say that the typescript compiler should also resolve these alias' in the declaration file process too.

The compilers job is to output valid javascript AND d.ts files for your typescript files, and it simply doesn't work in this valid scenario (using path alias' in tsconfig files).

I'm a little confused on this issue. It has been closed and labelled 'Working as Intended'. Am I to understand Typescript is intended to output invalid source? Seems odd.

Beggars can't be choosers, but using Typescript avoids many frustrating aspects of vanilla JS and I count relative imports ('../../../../../utils/parser') to be one of them. It would be amazing if Typescript could clean these up!

@codeitcody Seems like it. It's dumb that it would output something that simply doesn't work without some third-party package but that's the reality.

Well, isn't this a nice problem to fall upon.

It does seem very counterproductive to have a feature that essentially renders your app unusable without jumping through hoops (i.e installing more dependencies to workaround the issue).

This issue has been around for 2 years and has no official word on whether it's going to be implemented or not.

Considering this is required and basic functionality to use one of the best features of TypeScript in your Node.js projects, it's pretty awful how it is being treated.

@mhegazy Can you or someone else let us know if now two years later maybe the TypeScript team would possibly take a look at this again and reconsider?

webpack may help me to resolve path maps (or other tool likes babel-plugin-module-resolver) but not declarations (.d.ts).

All paths in declaration are not resolved. And declarations seem unusable.

Is there a way to achieve this? I have a custom react components library and I got this error when trying to use paths for an alias. I do the 2 bundles with rollup and the types with --emitDeclarationOnly

I can not use module-alias because it says:

WARNING: This module should not be used in other npm modules since it modifies the default require behavior!

Please help to upvote this post on Reddit: https://www.reddit.com/r/typescript/comments/a07jlr/path_maps_cannot_be_resolved_by_tsc_works_as/
Don't know why it needs this huge discussion here. It should be easy to solve this bug. An option in tsconfig and everyone can decide if he want's the current behavior (for whatever reason) or a working approach.

We had the same problem at Dropbox and open-sourced this transformer https://github.com/dropbox/ts-transform-import-path-rewrite

I have had the same experience multiple times now, I expect the path alias to be resolved but I keep forgetting that I have to install module-alias, update package.json and import it in the main file. Would be awesome if this was handledin the compile step by Typescript.

Ouch. This is a real blow to TypeScript. Where is the sense in this?

p.s Can we not just comment +1

Welcome to the club @def14nt. We're a happy group of dreamers, starry-eyed as we gaze into a better future, patiently awaiting the day when TypeScript will implement the simple and sensible compiler option to make our lives easier. When that day finally is upon us, be sure to check the sky for the portly pink bodies of the pigs as they majestically fly away into the sunset on their newfound wings.

Lol, I'll just install an npm extension for something the TypeScript team could add support for. Maybe they should stop adding more and more enhancements and add features that are this basic.

@mika-fischer
How to use https://www.npmjs.com/package/module-alias so that eslint stop to warn about 'Unresolved path '@root/bla/bla' (in JS files)? And how to enable autocompletion for such paths in WebStorm and VS Code?

For me, autocompleting imports works in VSCode by default in typescript projects.

@bobmoff Yes, seems like everything is good for import TS files from TS files.
But autocompletion and navigation for `require('@root/bla/bla') from TS files does not work.

I wish to translate my JS project to TS, and thought that I can rename js files to ts one by one.
Now I realize that it is so hard and unsupported neither by ts nor by IDEs, and I should rename all my js files to ts at once.

Because if I rename just one JS file to TS, all relative paths in build directory became broken (probably I should use "allowJs: true", but I have one project with 2 Gigabytes of JS files, it is so weird to compile them to the build dir %)).
Ok, I trying to solve this by module-aliases, and my IDE's navigation and autocompletion stop to work and eslint warns about 100500 'Unresolved paths'. I am already a bit hate TS, seems like migration for big JS projects is not so easy as TS-marketing people say. It seems like migration JS backend projects to golang is more simple :)

I'm successfully using tscpaths as a workaround.

Me too. I really recommend tscpaths . It works as it supposed to.

My simple workaround:

node -r ts-node/register/transpile-only -r tsconfig-paths/register index.js

Or with the pm2 process.yml

apps:
  - name: 'my-app'
    script: './dist/index.js'
    instances: 'max'
    exec_mode: 'cluster'
    out_file : '/dev/null'
    error_file : '/dev/null'
    node_args: ['--require=ts-node/register/transpile-only', '--require=tsconfig-paths/register']
    env_production:
      NODE_ENV: production

Just stumbled upon this, sometimes TypeScript can be a real pain in the ass.

I seriously donĀ“t understand why this thread goes on and on and on....
We all know about the "path hell", and that you (by using aliases) can
really clean
up that mess, everyone in this thread knows this!

The aliases are interpreted by the TypeScript compiler, it compiles exactly
as it should,
it should most definitely not poke around in the resulting javascript, if
you want to use
aliases you will have to solve this yourselves!

....or start threads at Apple, Google and Microsoft
asking them to implement functionality in their JavaScript engines so that
they can
interpet your aliases ;-)

The TypeScript compiler does exactly what it should do!

If you are working in the Angular world the road is paved, if you want to
run your
code directly in Node you will need a tool to resolve the paths, and I have
made
such tool just for you, itĀ“s been used in production for over a year now,
itĀ“s being
used by the largest newspaper here in Sweden, I made this so that you can
go bare
bone with Node, IĀ“m not trying to sell anything here, I donĀ“t make money
from this :)

And yes, there are tools like "tsmodule-alias" and similar hacks, you can
actually make it work
if you are very very careful, but itĀ“s a mess, there are workarounds using
ts-node,
shell scripts etc etc...yadda yadda

I finally felt that enough is enough so I locked myself away and made
TsPath
the compile time aliases

> npm install -g tspatj

myproject> tsc

myproject> tspath

or

myproject> tspath --f

headless (proved very useful on the build server)

and then youĀ“re done, your javascript files now have the
correct relative paths, isnĀ“t that what we want here?

Cheers! :)

https://www.npmjs.com/package/tspath

Den sƶn 13 jan. 2019 kl 22:20 skrev Fabio Spampinato <
[email protected]>:

Just stumbled upon this, sometimes TypeScript can be a real pain in the
ass.

ā€”
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/issues/10866#issuecomment-453866553,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAAy_7JYrwYo3KOLxpLWP0np5JVz2kQzks5vC6MogaJpZM4J6vZQ
.

@duffman

The aliases are interpreted by the TypeScript compiler, it compiles exactly
as it should, it should most definitely not poke around in the resulting javascript, if
you want to use aliases you will have to solve this yourselves!

Highly disagree. Unless you were joking, I really couldn't tell.

TypeScript should compile code that _works_ without needing a third-party tool to complete the job that was only partially implemented into the native compiler.

The TypeScript compiler does exactly what it should do!

If this thread was full of people requesting that tsc also do minification or some such, I'd agree with you. However it isn't. It's people requesting that the compiler generate executable code. I really don't think that's too much to ask from a compiler, do you?

And it is generating executable code if you donĀ“t use features which is
unsupported by JavaScript Engines, that should make a lot of sense right
there, for example: would you blame the C++ compiler if your application
uses dynamic link libraries and that the program wonĀ“t run on a machine
that doesnĀ“t have these installed?

This is a feature that can be utilized if you manage the relative paths,
take responsibility for them like Angular does with WebPack or as I do with
all my TypeScript projects with TSPath!

DonĀ“t use them if you donĀ“t understand how to set up a working environment,
I really donĀ“t think that this is Microsoft's responsibility here, they
provided a feature and hereĀ“s how it works,
it may not work as you want it or expect it to work but that does not make
it wrong!

Also, IĀ“m curious, are you seriously letting this hinder you from
developing using TypeScript?

Den mƄn 14 jan. 2019 kl 21:34 skrev Robert Main notifications@github.com:

The TypeScript compiler does exactly what it should do!

If this thread was full of people requesting that tsc also do
minification or some such, I'd agree with you. However it isn't. It's
people requesting that the compiler generate executable code. I really
don't think that's too much to ask from a compiler, do you?

ā€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/issues/10866#issuecomment-454151277,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAAy_7FeuOJAnI9bXYSVgf_YghJluTyGks5vDOnEgaJpZM4J6vZQ
.

This is a feature that can be utilized if you manage the relative paths, take responsibility for them like Angular does with WebPack or as I do with all my TypeScript projects with TSPath!

This is a feature which makes the compiler output broken code, code that could be working if they only wrote 1 line of code for properly resolving those paths.

The fact that TS needs an external bundler just so that the outputted code can be executed is plain ridiculous.

And it is generating executable code if you donĀ“t use features which is
unsupported by JavaScript Engines,

I've always understood that TypeScript was supposed to compile to JavaScript. If you're telling me that certain features are not supported by JavaScript engines then why exactly are they there?

would you blame the C++ compiler if your application dynamic link libraries and that the program wonĀ“t run on a machine doesn't have these installed?

No, but I would blame it if it let me link to other C++ code that didn't actually exist with no compiler error or warning.

You really donĀ“t understand this, do you? The code is not broken, if itĀ“s
broken it is because you have configured the compiler
to generate code that your "platform" does not support, in this case,
aliases!

In your case, donĀ“t use aliases, "you" donĀ“t support them, seriously!

Even if this would be a 1 line fix (of course thatĀ“s not the case) itĀ“s a
matter of what a compiler should and
should not do! This feature has been added in order to SUPPORT LOADERS not
the other way around, read up
on Path Mapping in the official documentation, so again, you are using it
wrong!

Again, this feature is for Loaders/Resolvers, you have misunderstood how it
works, so no, Microsoft
should not alter the compiler so that you can paste aliases without an
environment that supports it!

Den tis 15 jan. 2019 kl 04:41 skrev Fabio Spampinato <
[email protected]>:

This is a feature that can be utilized if you manage the relative paths,
take responsibility for them like Angular does with WebPack or as I do with
all my TypeScript projects with TSPath!

This is a feature which makes the compiler output broken code, code that
could be working if they only wrote 1 line of code for resolving those
paths.

The fact that TS needs an external bundler just so that the outputted code
can be executed is plain ridiculous.

ā€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/issues/10866#issuecomment-454256799,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAAy_zuWKV0qzzWt6_jZNgDLFt1TA0tMks5vDU3vgaJpZM4J6vZQ
.

They are there since Loaders use Path Mapping, thatĀ“s why itĀ“s supported!
And since you insist (like me) on using them without a Loader, what is the
problem with
using a tool so that you can make use of the feature?

Den tis 15 jan. 2019 kl 05:10 skrev Robert Main notifications@github.com:

And it is generating executable code if you donĀ“t use features which is
unsupported by JavaScript Engines,

I've always understood that TypeScript was supposed to compile to
JavaScript. If you're telling me that certain features are not supported by
JavaScript engines then why exactly are they there?

would you blame the C++ compiler if your application dynamic link
libraries and that the program wonĀ“t run on a machine doesn't have these
installed?

No, but I would blame it if it let me link to other C++ code that didn't
actually exist with no compiler error or warning.

ā€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/issues/10866#issuecomment-454260977,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAAy_25-ZmS235i1Ic7mvSzEt2QJDX6Bks5vDVTAgaJpZM4J6vZQ
.

Look, I see your point. I do. But part of the compilers job is to sanity check things one last time. At best code that compiles but doesn't run is inconsistent behavior and when I first read into this issue the documentation seemed to suggest behavior that clearly isn't there

Please point me to that section of the documentation.

tis 15 jan. 2019 kl. 05:31 skrev Robert Main notifications@github.com:

Look, I see your point. I do. But part of the compilers job is to sanity
check things one last time. At best code that compiles but doesn't run is
inconsistent behavior and when I first read into this issue the
documentation seemed to suggest behavior that clearly isn't there

ā€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/issues/10866#issuecomment-454263854,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAAy_8e5v8IV-ynmjRTeoC3cp5llwnsIks5vDVm8gaJpZM4J6vZQ
.

This feature has been added in order to SUPPORT LOADERS not
the other way around, read up
on Path Mapping in the official documentation, so again, you are using it
wrong!

https://austinknight.com/wp-content/uploads/2015/04/DesignVSUX.jpeg

@duffman Can't you see that people here just want this feature??? You are telling everyone that he/she is to stupid to understand how this "feature" should be used. OK - you can look at this that way but who knows - maybe it's the other way around...

By the way, my opinion is following:

As aliases are builtin in compiler and compilation of project with them is OK. It may make users think, that it works way it's suggesting (and this issue is pretty much good proof I'm right). It even seems illogical - why something works in "official" editor (vscode - especially when using "auto import" feature, vscode uses aliased path), why copiler also works OK, when resulting code is not working? Saying "js engine don't support it" makes me wanting to ask even more - wasn't TS meant as a thing to mitigate some of JS "problems"?

I would expect one of two solutions of this:
1) Correctly overriding imports with aliases
2) Showing a warning

Saying "it's correct behavior" is, I think, wrong. It's not. TS is not assembly language, not even a C/C++.

Development team should add support for alias resolution. I suggest add a
key for compiler resolution in tsconfig.

It would be nice Microsoft!!!!!!

We beg you, we need your help to improve applications with alias.

:( everybody here is sad and angry(, and hungry) because of lag of
consistency. Typescript is awesome, I love it...

We Love it!

Best regards a Homeless developer...

El mar., 15 de ene. de 2019 08:02, Mike S. notifications@github.com
escribiĆ³:

By the way, my opinion is following:

Aliases are builtin in compiler a compilation is OK. It may make users
think, that it should work like they think (and this issue is pretty much
good proof it's true). It seems illogical - why something works in
"official" editor (vscode - especially when using "auto import" feature,
vscode uses aliased path), why copiler also works OK, when resulting code
is not working? Saying "js engine don't support it" makes me wanting to ask
even more - wasn't TS meant as a thing to mitigate some of JS "problems"?

I would expect one of two solutions of this:

  1. Correctly overriding imports with aliases
  2. Showing a warning

Saying "it's correct behavior" is, I think, wrong. It's not. TS is not
assembly language, not even a C/C++.

ā€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/issues/10866#issuecomment-454384357,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ACKT9OqexgOaHH1vDFuRcO7U_r2DEC23ks5vDdFbgaJpZM4J6vZQ
.

. TS is not assembly language, not even a C/C++.

I really donĀ“t understand what you are trying to point out by establishing that TS is not C++, most of us are well aware of that I think!

We have also established that alias/path mapping is used in production all over the world, so naturally, VS Code should support that, but itĀ“s still not an argument for MS to craft the compiler to suit your setup!

What IĀ“m having a hard time understanding is why you keep at it, the compiler works as itĀ“s supposed to work, again, read the docs which clearly states what the feature is for!

I mean you can set up a working TS development environment with path aliases in like 2 minutes, if you donĀ“t want to use WebPack, you can use TSPath to resolve all paths in all js files in 1 second, add it to the package.json as a run script and you donĀ“t even have to think about it, the problem does not exist, the compiler stays the way it was meant to function and you can carry on happy hurray!?

Or if it is so important to you that the actual compiler does this for you, then I suggest you fork the compiler and implement it yourself, maybe it would be a big hit or maybe people are happy the way they are since they have set up their environments to support aliases.

Summoning the top five TypeScript contributors: @ahejlsberg @andy-ms @DanielRosenwasser @sandersn @sheetalkamat

Could the TypeScript team reconsider this issue? I think this thread offers some useful discussion on both viewpoints and given its recent popularity and the amount of time that's passed it should be looked at again.

The status of this issue left me no other choice but to demote TS to type checker duty only.
Babel now has a decent support for TS syntax and together with babel-plugin-module-resolver does the job of emitting working code for this use case just fine.
The only downside is duplicating bits of configuration from tsconfig.json as Babel does not care about TS configs. But it is an acceptable price for working absolute paths in node projects and as a bonus I get the whole ecosystem with brilliant things like babel macros.

This is the minimum setup I got working as a drop in replacement for tsc compiler:

  • npm install --save-dev @babel/cli @babel/core @babel/preset-env @babel/preset-typescript babel-plugin-module-resolver @babel/plugin-proposal-class-properties @babel/plugin-proposal-object-rest-spread
  • in package.json:
    tsc -> tsc && babel ./src --out-dir ./dist --extensions ".ts,.js"
  • in tsconfig.json:
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@mynamespace/*": ["src/*"]
    },
    "outDir": "./dist",
    "noEmit": true, <--
    "allowJs": true,
    "target": "ES2017",
    "module": "CommonJS",
    "lib": [
      "ES2017"
    ]
  },
  "include": [
    "./src/**/*"
  ]
}

  • in .babelrc:
{
  "presets": [
    "@babel/preset-typescript",
    ["@babel/preset-env", {
      "targets": {
        "node": true
      }
    }]
  ],
  "plugins": [
    ["module-resolver", {
      "root": ["./src"],
      "alias": {
        "@mynamespace": "./src"
      },
      "extensions": [".js", ".ts"]
    }],
    "@babel/plugin-proposal-class-properties",
    "@babel/plugin-proposal-object-rest-spread"   
  ]
}

I just want to use typescript with absolute path, but seems i have to config webpack or babel or something, it's too hard to achieve this simple feature, it should be easier šŸ˜ž

I acknowledge this problem, IĀ“m not sure IĀ“ve been aware of this specific
problem due to my own personal setup, or maybe I was :) itĀ“s not a super
heavy fix, the fix will simply be to simply (blindly) trust the distPath,
which is actually less and more simple code than the current solution, IĀ“ll
try to have a fix available by tomorrow...

Den mĆ„n 28 jan. 2019 kl 15:59 skrev 叶伟伟 notifications@github.com:

I just want to use typescript with absolute path, but seems i have to
config webpack or babel or something, it's toooo hard to achive!!!

ā€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/Microsoft/TypeScript/issues/10866#issuecomment-458164055,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAAy_1_T-An7swSND-xdBhL0HNHxQkm6ks5vHxBggaJpZM4J6vZQ
.

Leaving this here because an actual documented use case for the current behavior of paths was not mentioned in this thread: @types/ packages do not backport features with regards to semver. They do however include updated types for older APIs that I can use. E.g. I'm using history@2 when history@3 is the latest.

"paths": {
    "history": [ "history/v2" ]
}

The compiler would need an extra option to differentiate between type aliases and "code" aliases. If we change the behavior to actually emit the path aliases then we need to add the ability to the compiler to find the correct types version.

This is not an argument against the proposed behavior. I'd rather have emitted aliases and justā„¢ working solution for versioning of types. Just wanted to provide some context why changing this might not be as trivial as people think it is.

For the second time during a company-wide TS workshop, I've had to explain this inane and embarrassing behavior...

Seriously!

What kind of language compiler, especially one whose primary sales pitch is more correctness for JavaScript, produces broken code as a "feature"?!?!

I'm sorry to have sounded so frustrated in my comment, but the community's views here are seemingly being ignored and downplayed repeatedly.

Just look at how many times this has been referenced... What a waste of time and attention for so many people.

I understand your frustration, but lots of people feeling a behaviour is correct, doesn't mean it is the right thing to do.

TypeScript rewriting module identifiers is a slippery slippery slope. What has been expressed multiple times in this thread is that TypeScript is configurable to model the behaviour of other module resolvers and other build tools, not replace or implement them.

Just because TypeScript can be configured to resolve modules in flexible ways doesn't not mean that TypeScript emits "broken code". Certain loaders and bundlers that mirror this configuration would work just fine.

If we were to be critical of anything, we could blame the team for naming the option something that might look like it fixes a problem it was never intended to fix, though the documentation for the option makes it clear that it does not change the emit.

Because a particular tool doesn't solve a problem you have doesn't always mean it is that tools fault. It maybe you are just don't have all the tools you need to solve your problem.

@kitsonk everything you just said is way off the mark.

The issue is that TS will operate one way during development / testing, and another after compilation has completed.

If TS wants to be a module resolver, it needs to choose a pattern and stick to it. If I run something with ts-node it should operate exactly as if I compiled some TS and ran it with node.

It does not, and that is the problem.

Maybe module maps will alleviate the frustration in the future. But our position here along with the technical problems we want to solve are pretty explicit - path mapping reflects the behavior of an external resolution scheme (e.g. path mapping in AMD and System.js, aliases in Webpack and other bundlers). It doesn't imply we will change your paths.

I don't think any recent discussion has been constructive recently, nor do I foresee any future changes here, so I'm going to lock this issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bgrieder picture bgrieder  Ā·  3Comments

siddjain picture siddjain  Ā·  3Comments

wmaurer picture wmaurer  Ā·  3Comments

jbondc picture jbondc  Ā·  3Comments

Antony-Jones picture Antony-Jones  Ā·  3Comments