TypeScript: tsconfig noEmit error: Cannot reference tsconfig if it extends other tsconfig.

Bug Report

🔎 Search Terms

  • tsconfig.json
  • noEmit
  • extends
  • reference
  • Referenced project may not disable emit.

🕗 Version & Regression Information

Tried 4.8.0-beta, 4.7.3, 4.7.4, and 4.6.3

⏯ Playground Link

đŸ’» Code

Couldn’t reproduce this in Bug Workbench, but here is my minimal reproduction repo: https://github.com/ZerdoX-x-issue-reproducer/microsoft-TypeScript-49844

tsconfig.json:

{
  "references": [{ "path": "./tsconfig.test.json" }],
  "compilerOptions": {
    "noEmit": true
  }
}

tsconfig.test.json:

{
  "extends": "./tsconfig.base.json",
  "compilerOptions": {
    "composite": true,
    "noEmit": true
  }
}

tsconfig.base.json:

{
  "include": [
    "src/**/*.d.ts",
    "src/**/*.js",
    "src/**/*.ts",
  ],
  "compilerOptions": {
    "noEmit": true,
  }
}

🙁 Actual behavior

image

🙂 Expected behavior

image

đŸ€” Other info

SO question

UPDATE: Since this issue keeps receiving comments and attention, I would like to let you know that I don’t suffer from this issue anymore, but reproduction will be opened as long as my account exists 😃 Afair I was using SvelteKit and I just wanted to get proper type checking for all of my files: 1) source files which would or would not get bundled to be running on client and/or server 2) configuration files, where some files use ESM, some still support only CJS 3) tests. In newer projects I achieve this goal and do not stumble upon this issue, also it got easier now since new ESLint flat config which will be released in next major release.

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 5
  • Comments: 16 (5 by maintainers)

Commits related to this issue

Most upvoted comments

This issue has been marked ‘Working as Intended’ and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Question: is there an easy way to type-check with a single tsc run, without emit, and with different sets of files using different libs

No

add

"include": [],
"files":[]

in base config get rid of the error message

What also might be coming out is a desire for simplicity. To expound a little more, many people want the ability to say, “Type Check my entire monorepo” in one command. But that gets difficult when there are files intended to be included in the output (regular files from several scoped packages) and files not intended to be in the output (such as test files and configuration files).

Maybe clarity on what the recommendation is for monorepos would also be helpful? My goal is to avoid getting caught up in the chaos of turborepo, yarn workspaces, etc. I just want to work with simple NPM and TS for my monorepo.

Nice.

What are you trying to achieve?

@RyanCavanaugh, based on @ZerdoX-x’s other comments, I’m assuming that the goal is to have type checking for test files without including them in the project’s output. At least, that’s what I need, and that’s how I stumbled upon this issue.

TypeScript’s Project Reference Documentation suggested to me that Project References were the way to handle monorepos in NPM, keep TS working with tests, and keep the test files out of the build directory simultaneously. (Developers shouldn’t need to include a rm -rf command in their build step. The compiler should simply exclude all undesired files from the build output.) I haven’t found any clear documentation on how to handle this use case.

If you aren’t going to reopen the issue, would you be willing to give a reasonable alternative? Maybe there’s something we’re missing?

That doesn’t really answer my question, I guess.

Referencing a project does the following:

  • Changes imports of .ts files to their corresponding .d.ts files (under noEmit, those .d.ts files don’t exist)
  • Causes tsc -b to rebuild the upstream project if it’s out of date (if it doesn’t emit, this question doesn’t make any sense)
  • Adds any declaration outFile to the current project (under noEmit, those .d.ts files don’t exist)

Solution for us was to configure a base tsconfig.json with files as an empty array:

{
  "$schema": "https://json.schemastore.org/tsconfig",
  "files": [],
  "references": [
    { "path": "./tsconfig.root.json" },
    { "path": "./scripts/tsconfig.json" }
  ]
}

Then the error message Referenced project may not disable emit goes away.

Check out some examples:

In my head the ideal solution is just having an option to make tsc just hold the necessary reference declaration output in memory or in an internally handled temporary scratch/cache dir for the entirety of the command’s run without any reading or writing to the file system of the monorepo. An ever increasing size of devs are only using ts for intellisense in their IDE and as a CI test step or commit hook, no compiling. Can’t really find any solution to this myself 👀

This configuration doesn’t make any sense; every behavior of having a reference is dependent on the output files of the referenced project being present. What are you trying to achieve?

Of course this configuration doesn’t make any sense. Because this is not a configuration but a minimal reproduction of the issue. If you need to see my full production setup, I’ve added all configs to the my-full-configuration folder.