Skip to content

[@rollup/plugin-typescript] tsconfig declarationDir is ignored when using single file output #1230

Closed

Description

@CarrotB

Expected Behavior

Declarations generated at the specified location

Actual Behavior

Declarations generated at the same directory as the output file.

Additional Information

I'm using api-extractor to rollup d.ts files into a single one, so the declarations are output at a place that will be removed after
processing.
This works at version 8.3.1 with a problem that it generates file at relative location under output directory, that is when declarationDir is types and output.file is dist/index.js, declarations will be under dist/types. But after my collegue updated to 8.3.4 (by using ^8.3.1 in package.json), the behavior changes to that declarations generated at dist/, and the build progress breaks since api-extractor can't find the desired entry for d.ts rollup.

Activity

  1. dominikbulaj commented on Aug 1, 2022

    @dominikbulaj

    Also confirmed.

    In tsconfig.json I have: "declaration": false and in rollup.config.js I got

        typescript({
          compilerOptions: { declaration: true, declarationDir: './types' }
        }),
    

    When rollup runs declaration file(s) are placed in the output directory and not specified ('./types')

  2. himanshuchawla009 commented on Aug 2, 2022

    @himanshuchawla009
  3. shellscape commented on Aug 2, 2022

    @shellscape
    Collaborator

    @himanshuchawla009 please do not post "me too," "+1" type replies. They spam anyone who has notifications on for issues (e.g. all maintainers). Please use the reaction buttons on the original post in the issue instead.

  4. Alpha0723 commented on Aug 3, 2022

    @Alpha0723

    I got the same issue with 8.3.4. Now I have to create new tsconfig.types.json with declaration config
    "compilerOptions": {
    "declaration": true,
    "declarationDir": "./dist/types",
    "emitDeclarationOnly": true,
    }
    then use tsc command to generate d.ts to specific folder.
    It works but it's ugly. Hope it could be fixed asap.

  5. Basssiiie commented on Aug 12, 2022

    @Basssiiie

    I got the issue as well. Reverting back to version 8.3.3 fixes the issue, so it seems it was introduced in the 8.3.4 release. The only change in that release is this; #1201, which may very well be the cause (also there's other people talking about problems there as well).

    Easiest temporary fix for now: revert back to 8.3.3 and pin this version in your package.json.

  6. IronGeek commented on Sep 1, 2022

    @IronGeek

    I'm also having this problem with the latest version. And I think I found the problem with the recently merged PR #1201.
    Please correct me if my analysis is wrong.

    let baseDir =
    outputOptions.dir ||
    (parsedOptions.options.declaration
    ? parsedOptions.options.declarationDir || parsedOptions.options.outDir
    : null);
    if (!baseDir && tsconfig) {
    baseDir = tsconfig.substring(0, tsconfig.lastIndexOf('/'));
    }
    if (!code || !baseDir) return;
    this.emitFile({
    type: 'asset',
    fileName: normalizePath(path.relative(baseDir, id)),
    source: code
    });

    Asumming the parsedOptions.options.declaration is true and we're using single file output.
    The outputOptions.dir will be undefined, and the baseDir will be set to the parsedOptions.options.declarationDir value or fallback to parsedOptions.options.outDir if its not set (line 141).
    And since baseDir is now defined, the code generation will not be skipped and output files will be generated (line 149).
    This seems to be a solid logic, however on line 153 the filename for the file being generated is normalized and make relative to the baseDir.

    fileName: normalizePath(path.relative(baseDir, id)),

    So for example, if user set declarationDir to types, and foo/bar.d.ts is to be generated then:
    the expected filename relative to the output will be types/foo/bar.d.ts
    but the actual filename instead foo/bar.d.ts this is because:

    baseDir = '/some/absolute/path/to/output/types'
    id = '/some/absolute/path/to/output/types/foo/bar.d.ts'
    filename = relative(baseDir, id) => 'foo/bar.d.ts'

    we can see, that whatever value the declarationDir holds will be useless in single file output since the final filename will always be made relative to the declarationDir itself.

  7. rpearce commented on Oct 11, 2022

    @rpearce

    This appears to still be an issue as of the latest version, v9.0.0. Locking the version to 8.3.3 seems to be the only way to keep the original behavior working.

  8. yangliguo7 commented on Nov 23, 2022

    @yangliguo7

    I found that there will be similar problems in the case of multi-file output

    rollup.config.js
    
      output: [
        {
          dir: 'dist/cjs',
          format: 'cjs'
        },
        {
          dir: 'dist/es',
          format: 'es'
        },
      ],
    
    
    tsconfig.json
    
     compilerOptions: {
        declaration: true,
        declarationDir: "dist/types"
      },
    
    

    the error log

    @rollup/plugin-typescript: Path of Typescript compiler option 'declarationDir' must be located inside Rollup 'dir' option.
    

    Is this caused by the same problem?

  9. stale commented on Feb 2, 2023

    @stale

    Hey folks. This issue hasn't received any traction for 60 days, so we're going to close this for housekeeping. If this is still an ongoing issue, please do consider contributing a Pull Request to resolve it. Further discussion is always welcome even with the issue closed. If anything actionable is posted in the comments, we'll consider reopening it. ⓘ

  10. melissarh57 commented on Feb 17, 2023

    @melissarh57

    Did this ever get fixed? Or still just sticking with old rollup version for now?

  11. rpearce commented on Feb 18, 2023

    @rpearce

    I'm sticking with the old one at present. I don't believe I saw anything about this getting fixed...

  12. 2 remaining items

  13. deansimcox commented on Aug 23, 2023

    @deansimcox

    After some debugging, I've noticed that this issue comes up if you have a subfolder for the dir property.

    E.g this is the config we had

      output: [
        {
          file: pkg.main,
          format: 'cjs',
          exports: 'named',
          sourcemap: true,
        },
        {
          dir: 'build/esm',
          format: 'esm',
          exports: 'named',
          sourcemap: true,
          preserveModules: true,
          preserveModulesRoot: 'src',
        },
      ],
    

    The error went away when I changed build/esm to just build

  14. soeasyjx commented on Dec 11, 2023

    @soeasyjx

    Has this problem been solved yet

  15. rudevich commented on May 5, 2024

    @rudevich

    The problem is still here.

  16. cristian-eriomenco commented on May 21, 2024

    @cristian-eriomenco

    Can we re-open this? Its clearly not fixed and an outstanding issue.

  17. shellscape commented on May 21, 2024

    @shellscape
    Collaborator

    @cristian-eriomenco read this in its entirety and you'll have your answer: #1230 (comment)

  18. cristian-eriomenco commented on May 21, 2024

    @cristian-eriomenco

    @cristian-eriomenco read this in its entirety and you'll have your answer: #1230 (comment)

    Understood. Not going to fix it. Thanks for clarification.

  19. shellscape commented on May 21, 2024

    @shellscape
    Collaborator

    I'm not sure how you managed to misunderstand the very clear language in the message that the bot posted. but good luck to you.

    for onlookers and people who run across this issue in the future, we openly welcome community help to resolve this. the team of maintainers for roll-up is extremely small, and we are stretched extremely thin. we all have jobs and families.

  20. eimenanacreado commented on Dec 28, 2024

    @eimenanacreado

    Having the same problem with the latest versions : @rollup/plugin-typescript: Path of Typescript compiler option 'declarationDir' must be located inside the same directory as the Rollup 'file' option.

    I have back to those version and everything worked well :

    "@rollup/plugin-commonjs": "^25.0.3",
    "@rollup/plugin-json": "^6.1.0",
    "@rollup/plugin-node-resolve": "^15.1.0",
    "@rollup/plugin-terser": "^0.4.4",
    "@rollup/plugin-typescript": "^11.1.2",

  21. sbeka commented on Feb 19, 2025

    @sbeka

    helped, when install this version

    @rollup/plugin-typescript: ^11.0.0

  22. steebtom commented on Mar 16, 2025

    @steebtom

    Encountered the same error RollupError: [plugin typescript] @rollup/plugin-typescript: Path of Typescript compiler option 'declarationDir' must be located inside the same directory as the Rollup 'file' option.

    Fix:
    Just updated "declarationDir": "types" to "declarationDir": "dist/types" in tsconfig.json and this fixed it.

    package.json

    "@rollup/plugin-babel": "6.0.4",
    "@rollup/plugin-commonjs": "28.0.3",
    "@rollup/plugin-node-resolve": "16.0.1",
    "@rollup/plugin-terser": "0.4.4",
    "@rollup/plugin-typescript": "12.1.2",
    "@types/react": "19.0.10",
    "react": "19.0.0",
    "react-dom": "19.0.0",
    "rollup": "4.35.0",
    "rollup-plugin-peer-deps-external": "2.2.4",
    "rollup-plugin-postcss": "4.0.2",
    "typescript": "5.8.2"

    tsconfig.json
    { "compilerOptions": { "target": "es5", "module": "esnext", "lib": ["dom", "dom.iterable", "esnext"], "jsx": "react", "declaration": true, "declarationDir": "dist/types", "outDir": "dist", "strict": true, "moduleResolution": "node", "allowSyntheticDefaultImports": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true }, "include": ["src"] }

    Hope this helps someone.

  23. added a commit that references this issue on Jul 23, 2025
  24. eakarpov commented on Sep 12, 2025

    @eakarpov

    12.* version still has the error (11.* is ok)

  25. RahulCh010 commented on Nov 28, 2025

    @RahulCh010

    I found that there will be similar problems in the case of multi-file output

    rollup.config.js
    
      output: [
        {
          dir: 'dist/cjs',
          format: 'cjs'
        },
        {
          dir: 'dist/es',
          format: 'es'
        },
      ],
    
    tsconfig.json
    
     compilerOptions: {
        declaration: true,
        declarationDir: "dist/types"
      },
    

    the error log

    @rollup/plugin-typescript: Path of Typescript compiler option 'declarationDir' must be located inside Rollup 'dir' option.
    

    Is this caused by the same problem?

    Any idea how to resolve this for multi-file output? Even reverting to v11 didn't help for me

  26. ychavoya commented on Nov 28, 2025

    @ychavoya

    Hello! Regarding the multi-file output.

    Checking the plugin's implementation, it looks like the declarationDir must be inside a directory controlled by rollup, in case a different plugin wants to do something with the declaration files. So having the types outside of an output dir (such as dist/types when the output is on dist/cjs), would not respect that. See here:

    When generating declaration files, the outDir must be set and be pointed to Rollup's output dir (or some subfolder). This allows us to use Rollup's asset emit API, and other plugins can then intercept these assets to potentially bundle the declaration files later.

    However, there is a workaround, such as this one found by zeakd. Basically there are two different rollup configs:

    • In one, the typescript is compiled into cjs and the types are generated. This one uses the dist dir as output dir, but renames the index to be in a cjs subfolder. This allows the usage of dist/types as an output dir for the declaration files.
    • In the other, the typescript is compiled into es but without emitting declaration files. This config is as usual.

    The main disadvantage of this approach is that now you have to maintain two configs, though you can probably have a common config object and spread the common configuration between them.

    Here's an example I managed to make:

    rollup.config.js

    const typescript = require("@rollup/plugin-typescript");
    
    module.exports = [
      {
        input: "src/index.ts",
        output: {
          dir: "dist",
          entryFileNames: "cjs/index.js",
          format: "cjs",
        },
        plugins: [
          typescript({
            tsconfig: "./tsconfig.json",
            declaration: true,
            declarationDir: "dist/types",
          }),
        ],
      },
      {
        input: "src/index.ts",
        output: {
          dir: "dist/es",
          format: "es",
        },
        plugins: [
          typescript({
            tsconfig: "./tsconfig.json",
          }),
        ],
      },
    ];

    tsconfig.json:

    {
      "compilerOptions": {
        "target": "es5",
        "sourceMap": true,
        "inlineSources": true,
      },
      "exclude": [
        "node_modules"
      ]
    }

    This provides the following result:

    dist
    ├── cjs
    │   └── index.js
    ├── es
    │   └── index.js
    └── types
        └── index.d.ts
    

    Hope this helps!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions