Typescript: tsc: TS5053: Option 'noEmit' cannot be specified with option 'composite'

Created on 21 Feb 2020  ·  21Comments  ·  Source: microsoft/TypeScript


TypeScript Version: 3.9.0-dev.20200220 (broken in 3.8.2)


Search Terms: TS5053: Option 'noEmit' cannot be specified with option 'composite'

Code

{
  "compilerOptions": {
    "composite": true
  }
}

Expected behavior:

Run a type-check with no errors, as in 3.7 and previous versions.

Actual behavior:

# npx tsc --noEmit
tsconfig.json:3:5 - error TS5053: Option 'noEmit' cannot be specified with option 'composite'.

3     "composite": true,
      ~~~~~~~~~~~

Found 1 error.

Additional comments:

We use composite in our tsconfig.json to ensure the output directory structure is always the same.
We also use --noEmit in our CI pipelines to ensure type-checking before building a Docker image.

Is the --noEmit the best way to do type-checking without the overhead of running an entire build (with output files) or this breaking change should really be reverted?

Related Issues:

36588 - attempt to remove the composite from tsconfig.json and use as CLI flag when building project

Most helpful comment

I understand that composite needs metadata to work properly, but now there's no way to run a simple type-check within the CLI without actually building something.

composite was released in TypeScript 3.0 and worked with noEmit until 3.8.

I'm really not against that change, but as #36588 blocks us from removing composite from tsconfig.json and using it on compile-time, there's no way to run a type-check without build artifacts.

All 21 comments

Is the --noEmit the best way to do type-checking without the overhead of running an entire build (with output files) or this breaking change should really be reverted?

composite requires declaration output to actually do incremental work - use emitDeclarationsOnly instead of noEmit.

Is the --noEmit the best way to do type-checking without the overhead of running an entire build (with output files) or this breaking change should really be reverted?

composite requires declaration output to actually do incremental work - use emitDeclarationsOnly instead of noEmit.

Thanks for the quick answer! When using emitDeclarationOnly an entire build tree is created with the .d.ts files. We're looking for an alternative to use the composite flag when building (we can't use as CLI flag due to #36588) while using noEmit to do a quick type-checking without the I/O overhead.

Those declaration files are the metadata that incremental and composite modes use to determine which files need to be checked in subsequent builds. Without them, no work is actually incremental.

I understand that composite needs metadata to work properly, but now there's no way to run a simple type-check within the CLI without actually building something.

composite was released in TypeScript 3.0 and worked with noEmit until 3.8.

I'm really not against that change, but as #36588 blocks us from removing composite from tsconfig.json and using it on compile-time, there's no way to run a type-check without build artifacts.

I understand that composite needs metadata to work properly, but now there's no way to run a simple type-check within the CLI without actually building something.

composite was released in TypeScript 3.0 and worked with noEmit until 3.8.

I'm really not against that change, but as #36588 blocks us from removing composite from tsconfig.json and using it on compile-time, there's no way to run a type-check without build artifacts.

I've the same problem in a mono repo. so that I can continue to work, I created a tsconfig.test.json

{ "extends": "./tsconfig.json", "compilerOptions": { "composite": false } }

to use it with --noEmit:

"lint": "tsc -p tsconfig.test.json --noEmit && eslint \"**/*.{ts,tsx}\" --quiet --fix",

So I can lint my packages at least

I have the same problem but with noEmit and incremental. Is there any other way to run a type-check without building anything?

Don't use incremental? If you don't want anything built, you can't get any speedup from incremental; the built things are what incremental uses in place of normal inputs to save time.

@weswigham Sorry, to clarify: we have incremental set in our tsconfig, which until now we've used for our production builds, local environment builds and type-checks on commit. For the type-check on commit we've passed --noEmit as a CLI argument. As far as I can tell what we have to do now is add a separate tsconfig for type-checking as @dotupNET suggested.

So I'm wondering if there's a way to avoid having two config files.

We have a similar issue. We have a monorepo and use path references, which requires composite: true. We used to use --noEmit to perform type-checking on commit hook, but now it doesn't seem to be possible without actually building files.

agree, --noEmit used to work perfectly with composite: true and incremental: true, pls bring it back.

It did not "work perfectly" - it didn't do what it claimed to do (intelligently reuse build outputs as inputs where possible); the usage of noEmit completely negated what the composite and incremental flags were meant to achieve. You can get the same behavior (build performance-wise) by _not having them set_.

@hollg you could pass --incremental false --noEmit rather than just --noEmit for the CI pass, no?

The problem is that they can not be unset in command line. During development, it's good to have them, but for checking during commit, it'd be better to do something like tsc --noEmit --composite false. But right now tsc doesn't allow to have it in command line, so we basically need to have separate config files. See https://github.com/microsoft/TypeScript/issues/36588

composite has other baggage that ties it to tsconfig usage (namely project references), so you need a separate config file (so you can redefine the build without using project references), but for incremental just using --incremental false as an override on the command line works fine, afaik?

I think allowing composite to be set to false (not true) seems like a better solution here. Looking into this.

@weswigham

@hollg you could pass --incremental false --noEmit rather than just --noEmit for the CI pass, no?

This works, thanks!

@weswigham right now its impossible to use composite projects, where one of the project is react-based. Because create-react-app adds "noEmit": true to tsconfig automatically (even if you set it to false, once you run app it will change it to true) it makes impossible to use react and composite projects.

Its a big issue because guess over 95% of react users use create-react-app.

Should create-react-app be adjusted to use emitDeclarationOnly instead? Afaik it uses noEmit because webpack handles (non-declaration) emit; but blocking _all_ emit does make the composite (and incremental) flags do _nothing_ (extra or better, compared to a build without them set).

Closing this since we are now allowing passing --composite false from the command line

you could pass --incremental false --noEmit rather than just --noEmit for the CI pass, no?

For someone who found this thread after upgrading to TypeScript 3.8 and after passing --incremental false together with --noEmit but gets another error TS5069: Option 'tsBuildInfoFile' cannot be specified without specifying option 'incremental' or option 'composite'. the solution is passing --tsBuildInfoFile null as well (yeah, null). This ain't intuitive, so it might be helpful.

@weswigham right now its impossible to use composite projects, where one of the project is react-based. Because create-react-app adds "noEmit": true to tsconfig automatically (even if you set it to false, once you run app it will change it to true) it makes impossible to use react and composite projects.

Its a big issue because guess over 95% of react users use create-react-app.

Eject from create-react-app.

Was this page helpful?
0 / 5 - 0 ratings