Typescript: Typescript build not working as expected with symlinks.

Created on 7 Jul 2016  路  15Comments  路  Source: microsoft/TypeScript

TypeScript Version: 2.0.0-dev.20160630

Code

When I use a symlink in Windows I'm getting different build results. I haven't tested this with Mac/Linux yet.

dev
  app
    node_modules
      test
        foo.ts
    index.ts

Builds to:

dev
  app
    bld
      node_modules
        test
          foo.js
      index.js
    ...

Using symlink

mklink /D "c:\dev\app\node_modules\test\" "c:\dev\test\"
dev
  test
    foo.ts
  app
    node_modules
      test => /dev/test
    index.ts

Builds to:

dev
  app
    bld
      app   
        index.js
      test
        foo.js
    ...

Expected behavior:

Building with and without a symlink should build the same.

Actual behavior:

Building without a symlink behaves normally. Building with a symlink does not treat the directory as a link but uses the actual location of the linked directory. This causes problems with module resolution.

Bug Fixed

Most helpful comment

I am experiencing the same issue. Looking forward to a fix.

All 15 comments

This appears to be a problem on Mac/Linux. Symlinked node_modules do not build the same way installed node_modules do. This was not a problem in ts 1.8.x.

This comes up for me because I am working on three libraries where two depend on the other. So I have library A, that B and C depend on. For development harmony, I use symlinks to work on them all at the same time.

The alternatives would be-

  1. To regularly push a changes to library A for B to npm update
  2. To regularly copy the contents of A to B/node_modules/A and C/node_modules/A
  3. To clone A to B/node_modules/A and regularly copy it's contents to C/node_modules/A (or vice versa)

So i'd much prefer symlinks if possible.

+1

The problem here is that the compiler will follow an import to test then resolve its realpath (a change made in TS 2.0 to support npm link scenarios) to /dev/test/foo.ts, and thus your program really has two files, /dev/app/index.ts and /dev/test/foo.ts, and there is no way to tell the compiler not to build /dev/test/foo.ts, as all source files (i.e. .ts files) are required to generate output.

An alternative is to use intermediate .d.ts files for your projects. i.e. have /dev/test/foo.d.ts instead of /dev/test/foo.ts. .d.ts files do not generate outputs, and will not participate in building your output folder structure. this means that when building your /dev/test you need to generate a declaration file (i.e. use --declaration).

Ultimately the fix would be the compiler to understand symlinks for all files, and unify files that come from the same real path. this is not a simple change, and would require some major changes to how programs are created and used.

I am experiencing the same issue. Looking forward to a fix.

have similar issue when using npm link, already tried setting outDir and exclude in the tsconfig.json

Here's what I tried to reproduce this:

mkdir test; cd test
echo 'export const x = 0;' > foo.ts
echo '{ "name": "test" }' > package.json

cd ..; mkdir app; cd app
npm link ../test
echo 'import { x } from "test/foo"; x + 1;' > index.ts
echo '{ "compilerOptions": { "outDir": "bld" }, "exclude": [] }' > tsconfig.json
tsc

This writes to bld/app/node_modules/test/foo.js and bld/app/index.js. (I made an issue regarding the extra app wrapper directory: #11977.) That's the same output I get if I remove the symlink and copy-paste test into node_modules.

Could you provide exact instructions to reproduce your problem?

As an aside, trying to compile the output of node_modules (by overriding the default "exclude") is a bad idea anyway; imagine the compile times if you had 100 imported libraries in there.

I am using typescript 2.0.6 and having the same issues with symbolic links.

I have put together a simple example that demonstrates the problem

https://github.com/jmc420/typescript_examples/tree/master/symlink_problem

The README explains the issue. The question is whether it is possible to get the compiler
to generate the same output regardless of whether a typescript file is a symbolic link or not.

Have you tried changing the module resolution in your tsconfig to "classic"?

https://www.typescriptlang.org/docs/handbook/module-resolution.html

Thanks. Using "classic" module resolution is the answer.

classic module resolution generates the code in the way that I want but using "classic" means that typings in the node_modules directory are not found. Is it possible to use classic module resolution and find the typings in the node_modules directory?

Fixed by #12020

I think it's not working in 2.2.0-dev.20161113 version. Which version will include this functionality?
I use node 7.0.0 on MacOs Sierra

The code works fine when I don't use npm link library
Error:(25, 10) TS2345:Argument of type '(group: AbstractControl) => { [key: string]: any; }' is not assignable to parameter of type 'ValidatorFn'.
Types of parameters 'group' and 'c' are incompatible.
Type 'AbstractControl' is not assignable to type 'AbstractControl'. Two different types with this name exist, but they are unrelated.
Types of property 'validator' are incompatible.
Type 'ValidatorFn' is not assignable to type 'ValidatorFn'. Two different types with this name exist, but they are unrelated.
Types of parameters 'c' and 'c' are incompatible.
Type 'AbstractControl' is not assignable to type 'AbstractControl'. Two different types with this name exist, but they are unrelated.
Types of property 'validator' are incompatible.
Type 'ValidatorFn' is not assignable to type 'ValidatorFn'. Two different types with this name exist, but they are unrelated.
Types of parameters 'c' and 'c' are incompatible.
Type 'AbstractControl' is not assignable to type 'AbstractControl'. Two different types with this name exist, but they are unrelated.

@ert78gb Please provide steps to reproduce your error.

  • nvm use 7.0
  • create project A with npm init
  • npm link in project A folder
  • create project B, with angular-cli
  • npm link A in project B folder

If I use IntelliJ to auto build, or if I use ng serve, ng build I got the same error.

If I don't use linked library the builds work the app is running with the expected result

That may be because of the TypeScript version used by IntelliJ / angular-cli. This fix is in typescript@next and will be added to the next 2.1 release, so it should work whenever your tools are updated to use that.

Was this page helpful?
0 / 5 - 0 ratings