ts-loader generating definition file in wrong directory

Created on 30 Apr 2016  Â·  30Comments  Â·  Source: TypeStrong/ts-loader

I am creating a new issue here as discussed in typescript Issue
I am using typescript version 1.9.0-dev.20160412 and ts-loader version 0.8.2 as below
My tsconfig.json is as below:

{
  "compileOnSave": false,
  "buildOnSave": false,
  "compilerOptions": {
    "module": "commonjs",
    "target": "es6",
    "moduleResolution": "node",
    "preserveConstEnums": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "noImplicitAny": false,
    "noEmitOnError": false,
    "forceConsistentCasingInFileNames": true,
    "removeComments": false,
    "sourceMap": true,
    "jsx": "react",
    "outDir": "./lib",
    "declaration": true
  },
  "exclude": [
    "node_modules",
    "dist",
    "typings/browser",
    "typings/browser.d.ts"
  ]
}

My project folder structure is as below:

work/
`-- projects
    `-- projectx
        |-- dist
        |-- src
        `-- tsconfig.json

I am trying to compile and generate .d.ts files inside the 'lib' dir but this creates the .d.ts file inside folder with parent attached to lib i.e

work/
`-- projects
    `-- projectx
        |-- src
        |-- dist
        |   `-- work
        |       `-- projects
        |           `-- projectx
        |               `-- dist
        |                   `-- lib
        |                       `-- src
        |                           `-- index.d.ts
        `-- tsconfig.json

I was expecting it to be as :

work/
`-- projects
    `-- projectx
        |-- dist
        |   `-- lib
        |       `-- src
        |           `-- index.d.ts
        |-- src
        `-- tsconfig.json 

dist dir above is given in the webpack.config.js as below:

output: {
    path: path.join(__dirname, '/dist'),
    filename: outputFile,
    library: libraryName,
    libraryTarget: 'umd',
    umdNamedDefine: true
  }

Sample project with the above mentioned error Sample Project.
It works as expected with the version 0.8.0 of ts-loader

Most helpful comment

@johnnyreilly @gluons Sorry, my bad, you are right. Added the outDir to the compilerOptions and it works as expected.

    module: {
        rules: [
            {
                test: /\.tsx?$/,
                loader: "ts-loader",
                options: {
                    compilerOptions: {
                        outDir: './dist'
                    }
                }
            }
        ]
    }

Thank you!

All 30 comments

Same issue

Actually even with 0.8.0 it outputs far more of the directory structure than I would expect. Instead of

dist/
`--index.d.ts
`--index.js
`--directives
   `--directive.js
   `--directive.d.ts

I get:

dist/
`--index.d.ts
`--index.js
`--src/module/directives
   `--directive.js
   `--directive.d.ts

Strangely though, this problem only happens if I specify files other than index.ts in the files section of my tsconfig.json.

So I did some further testing. It turned out I can do this but I needed to create a tsconfig.build.json specifically for my build and pass it to the loader. Also outDir needs to be ./ or it will be appended to the output folder from webpack.

In 0.8.2 this is definitely broken though, it expands the full original root path for each d.ts file it outputs.

I have the same problem with 0.8.2. 0.8.1 seems to work.

Can confirm (since 0.8.2). This was reported on #186.

Yep, seeing this too. Stuck on 0.8.1 for now (really wish I could comment package.json but oh well)

I can confirm I'm seeing this issue on 0.8.2. The d.ts files are being generated in a full absolute on the file system, rather than the relative path in the project. Is there any ETA on a resolution?

Expected:

dist/
  app/
    Class.d.ts

Actual:

dist/
  users/
    shared/
      workspace/
        project/
          dist/
            app/
                Class.d.ts

238 is a duplicate issue that includes a minimal example demonstrating this bug

Any workarounds? Maybe somehow explicitly set the path?

Workaround for now is give path as
"outDir": "../../../../lib"

Number of backslashes = directory depth from root (/) till your project

That sounds terrible, but maybe we are getting close to a solution. If you
move the project to a different directory you just have the bug again,
except this time it can leak _outside_ the project. However, if the depth
of the project was detected programmatically and the outDir corrected
automatically that would solve the issue.

On Sun, Sep 4, 2016, 16:25 Shubhendu Shekhar Singh [email protected]
wrote:

Workaround for now is give path as
"outDir": "../../../../lib"

Number of backslashes = directory depth from root (/) till your project

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/TypeStrong/ts-loader/issues/190#issuecomment-244626621,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAUXacKtj-MilMUtXzGUbk5S4b1nDq0Rks5qmylRgaJpZM4ITZ-J
.

+1

Fixed on 0.9.3

Same issue in 4.2.0

Same issue in 4.3.0

Would someone like to supply a minimal repro repo and investigate this?

@johnnyreilly OK. I've created it.

Here: https://github.com/gluons/ts-loader-declaration-issue

Should I raise new issue?

Thanks - it's fine to use this issue! Now, let's see how dedicated you are... Would you be up for doing some investigation?

To give you a heads up, here's the pr that fixed the issue last time: https://github.com/TypeStrong/ts-loader/pull/307/files

Looks like the important stuff was in the ensureTypeScriptInstance function in the index.ts file.

Of course that was a long time ago, the relevant code now seems to be in the provideDeclarationFilesToWebpack function of the afterCompile.ts file.

Possibly worth investigating what compilation.compiler.context is these days - I've an idea it may have changed with webpack 4 but I'm not certain.

Also worth checking: when did this functionality stop working? Which version of ts-loader first presents the problem?

I don't know which version that this problem begin.

How can I help you? Maybe I will help you when I'm free.

Adding something like context: path.resolve("src") to the Webpack config is fixing this issue for me. Thanks @johnnyreilly!

I think I have this same problem — I have reproduced it here: https://github.com/jamesots/ts-loader-test

In my case, it seems to be because my tsconfig.json isn't in the root directory. In this simple test case I could move the tsconfig.json, but I can't in my real (much more complex) project.

The problem appears to be in provideDeclarationFilesToWebpack() in after-compile.ts, where it uses path.relative() to compare the webpack context directory with the declaration file name. It should be using the typescript project directory instead. I'm not sure how to fix it though, without potentially breaking other things.

Thanks for sharing the workaround @gluons!

@jamesots

I'm not sure how to fix it though, without potentially breaking other things.

My advice: get something that seems to work for you. Ignore failing tests and submit a PR. I'll take a look and advise. If it's promising I'll try and help you get it over the finish line

Got the same issue with ts-loader 4.4.1.

my tsconfig.json for webpack looks like this.

{
    "extends": "./tsconfig",
    "compilerOptions": {
        "rootDir": "./src",
        "outDir": "./dist/umd"
    }
}

webpack.config.js

    output: {
        ...
        path: config.getOutDirectory(),
    },
    ...
     {
            test: /.*\.tsx?$/,
            use: [{
                loader: "ts-loader",
                options: {
                    configFile: config.getTsConfigFile(),
                },
            }],
        ...

This will create following folder structure:

  |-- dist 
  |    |- umd 
  |       |- *.d.ts files
  | -- umd
        |- bundle.js 

What worked for me now was to add compilerOptions to ts-loader options and set the outDir to the basename of my output directory ( /absolute/path/to/dist/umd -> umd )

{
 ...
 {
            test: /.*\.tsx?$/,
            use: [{
                loader: "ts-loader",
                options: {
                    compilerOptions: {
                        outDir: basename(config.getOutDirectory()),
                    },
                    configFile: config.getTsConfigFile(),
                },
            }],
   ...
}

I have the same problem. The path's base when generating declaration seems to be the outDir. But for the typescript compiler it's the project root. I can take a look at this and submit a PR if I find a solution.

@johnnyreilly I've investigated provideDeclarationFilesToWebpack with my repo.
Thank you for your hint.

compilation.compiler.context is my current working directory.
declarationFile.name will give the absolute path to declaration file within the same place as source file.

So, after path.relative, the final path will contain src

default


If I set outDir in my tsconfig.json to dist, declarationFile.name will contain dist instead.
(This may be correct 🤔)

default


Maybe I should path.relative the declarationFile.name with webpack's output.path.
But I don't know what to do. 😅

Hey @gluons,

Thanks for the detail. The issue should be resolved by this PR: https://github.com/TypeStrong/ts-loader/pull/822

I'm planning to merge and release this in future. Feel free to test out the PR ahead of release. Early feedback is always welcome!

Hello, for me the issue seems to be back since 5.0.0. Versions 4.3.0 and 4.5.0 were fine.

I made a minimal repo to reproduce the problem:
https://github.com/tedchirvasiu/ts-loader-declaration-output-dir-issue

Running "npm run build" will correctly place the .d.ts files in the dist folder since I'm using 4.5.0 in the example repo. However, if I run "npm i ts-loader@latest" (which is 5.3.0 at the time of posting this) and then build, it puts the d.ts files at the root of the project rather than inside the dist folder.
Webpack's output path is set to "path.resolve(__dirname, 'dist')" and tsconfig's "outDir" is set to "./".
The issue seems to be present since 5.0.0.

Hey @tedchirvasiu

I'm pretty sure the changed behaviour is intentional - see the details here:

https://github.com/TypeStrong/ts-loader/pull/822

@tedchirvasiu It works as intended in ts-loader v5. It's breaking change.
You have to set outDir or declarationDir to specify the output directory of declaration files.

From @JonWallsten in #882 :

I would have to say that it's intended (but maybe unwanted in some cases?). It's TypeScripts default behavior to do this. If you don't add outDir or declarationDir it might be intended, and you could get annoyed by a warning, since it's in the context of TypeScript isn't wrong.

@johnnyreilly @gluons Sorry, my bad, you are right. Added the outDir to the compilerOptions and it works as expected.

    module: {
        rules: [
            {
                test: /\.tsx?$/,
                loader: "ts-loader",
                options: {
                    compilerOptions: {
                        outDir: './dist'
                    }
                }
            }
        ]
    }

Thank you!

Was this page helpful?
0 / 5 - 0 ratings