How to fix Option 'declaration' cannot be used without 'emitDeclarationOnly' when 'noEmit' is set in TypeScript
This error occurs when TypeScript compiler options conflict in your tsconfig.json file. The declaration option requires either emitDeclarationOnly or a normal emit mode, but noEmit prevents all file emission. The fix involves choosing one option strategy and removing conflicting settings.
Quick fix
Fixes TS5053
{
"compilerOptions": {
"noEmit": true // Pick ONE strategy - this disables ALL output
}
}- Identify your primary emit strategy
- Remove conflicting options from tsconfig.json
- Check for inherited configs in extends
- For monorepo/workspace setups, use separate configs
{"compilerOptions": {"noEmit": true // Pick ONE strategy - this disables ALL output}}Option 'declaration' cannot be used without 'emitDeclarationOnly' when 'noEmit' is set
What this error means
TypeScript's compiler options for file emission fall into distinct categories: - **noEmit**: Disables all output - no .js files, source maps, or declaration files - **emitDeclarationOnly**: Only emits .d.ts declaration files, no JavaScript - **declaration**: Emits both .js and .d.ts files When you have `"noEmit": true` in your configuration, TypeScript doesn't emit anything at all. If you also try to use `"declaration": true` (which requires some form of output), or `"emitDeclarationOnly": true` (which contradicts noEmit by emitting declarations), TypeScript throws error TS5053. This conflict typically arises when: 1. Your tsconfig.json extends a base configuration that sets noEmit 2. You're overriding those settings inconsistently 3. You have conflicting compiler options passed via CLI and config file
Typical symptoms
- TypeScript compilation fails immediately with TS5053 error
- The error appears after updating TypeScript or changing tsconfig.json
- Building or type-checking works in some contexts but fails in others
- You're using a monorepo where tsconfig files extend shared configs
- The error prevents any build process from starting
Common causes
- Your tsconfig.json sets noEmit: true while also specifying declaration: true or emitDeclarationOnly: true
- You're extending a base tsconfig (like tsconfig.lib.json) that has conflicting options
- An extended config has noEmit set, and you're trying to override with emitDeclarationOnly
- You specified --noEmit on the CLI while your tsconfig has emitDeclarationOnly: true
- A tool (like tsc --noEmit) is overriding your configuration
How to fix "Option 'declaration' cannot be used without 'emitDeclarationOnly' when 'noEmit' is set"
First, determine what you need:
- Type-checking only (CI/CD linting): Use "noEmit": true
- Generate declarations only (type-only packages): Use "emitDeclarationOnly": true
- Generate both .js and .d.ts (libraries/apps): Use "declaration": true (with noEmit: false or omitted)
Add this to your tsconfig.json based on your use case:
{
"compilerOptions": {
"noEmit": true // Pick ONE strategy - this disables ALL output
}
}OR
{
"compilerOptions": {
"emitDeclarationOnly": true, // Emit only .d.ts files
"declaration": true
}
}OR
{
"compilerOptions": {
"declaration": true, // Emit .d.ts alongside .js
"noEmit": false // Explicitly allow emission (or omit, default is false)
}
}Open your tsconfig.json and ensure you don't have both noEmit and emitDeclarationOnly:
WRONG:
{
"compilerOptions": {
"noEmit": true,
"emitDeclarationOnly": true // These conflict!
}
}WRONG:
{
"compilerOptions": {
"noEmit": true,
"declaration": true // This requires output!
}
}CORRECT (type-checking only):
{
"compilerOptions": {
"noEmit": true
}
}CORRECT (declarations only):
{
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true
}
}If your tsconfig extends a base config, the conflict may come from there:
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"emitDeclarationOnly": true // Overrides noEmit from base
}
}Check what's in tsconfig.base.json:
cat tsconfig.base.json | grep -A5 '"compilerOptions"'If the base config has "noEmit": true, you must explicitly override:
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"noEmit": false, // Override inherited noEmit
"emitDeclarationOnly": true,
"declaration": true
}
}In a monorepo with multiple packages, create separate TypeScript configs:
tsconfig.json (shared base, for type-checking):
{
"compilerOptions": {
"noEmit": true,
"target": "ES2020",
"module": "ESNext"
}
}tsconfig.build.json (for building libraries):
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": false,
"declaration": true,
"outDir": "./dist"
},
"include": ["src/**/*"]
}Then in your build script:
# Type check (no output)
tsc --noEmit
# Build (emits .js and .d.ts)
tsc --project tsconfig.build.jsonTest your configuration:
# Check for errors (no output files created)
npx tsc --noEmit
# Or build if using emitDeclarationOnly
npx tscIf successful, you should see no TS5053 error. Check that:
- Type-checking passes
- If you have emitDeclarationOnly, .d.ts files are created
- If you have declaration: true, both .js and .d.ts files are created
- If you have noEmit: true, no output directory is created
Advanced notes
### Understanding the Three Options
noEmit: true
- Use case: CI/CD type-checking, linting, IDE checking
- Output: None (zero files written)
- Common in: GitHub Actions workflows, pre-commit hooks, test suites
emitDeclarationOnly: true
- Use case: Pure TypeScript libraries that need .d.ts files only
- Output: Only .d.ts files (no .js)
- Requires: Some other tool (Babel, swc, esbuild) to handle JavaScript transpilation
- Common in: Libraries with separate JS build process, monorepo packages
declaration: true (default noEmit: false)
- Use case: Applications and libraries with direct TypeScript output
- Output: Both .js and .d.ts files
- Common in: Traditional build setups, full-stack applications
### CLI Override Behavior
If you run tsc with CLI flags, they override tsconfig settings. Be careful with:
# This conflicts if tsconfig has emitDeclarationOnly
npx tsc --noEmit
# This conflicts if tsconfig has noEmit
npx tsc --emitDeclarationOnlyTo avoid surprises, specify the strategy in tsconfig.json and let scripts use it:
npx tsc # Uses tsconfig.json settings
npx tsc --project tsconfig.build.json # Uses alternate config### Multi-package monorepos
Nx, Turborepo, and similar tools often set conflicting configs. If you get this error in a monorepo:
1. Check the root tsconfig.json and any extended configs
2. Ensure each package's tsconfig.json is explicit about its emit strategy
3. Use the tool's documentation (Nx: project.json, Turborepo: turbo.json) to override compiler options
Frequently asked questions
- What does "TS5053" mean?
- ts files When you have "noEmit": true in your configuration, TypeScript doesn't emit anything at all. If you also try to use "declaration": true (which requires some form of output), or "emitDeclarationOnly": true (which contradicts noEmit by emitting declarations), TypeScript throws error TS5053. This conflict typically arises when: 1.
- How do I fix "TS5053"?
- This error occurs when TypeScript compiler options conflict in your tsconfig.json file. The declaration option requires either emitDeclarationOnly or a normal emit mode, but noEmit prevents all file emission. The fix involves choosing one option strategy and removing conflicting settings.
- What causes "TS5053"?
- Your tsconfig.json sets noEmit: true while also specifying declaration: true or emitDeclarationOnly: true You're extending a base tsconfig (like tsconfig.lib.json) that has conflicting options An extended config has noEmit set, and you're trying to override with emitDeclarationOnly
- Is the "TS5053" error serious?
- Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.
Official resources & further reading
- ๐TypeScript Official Documentation
- ๐TypeScript: TSConfig Option - noEmit(Official Docs)
- ๐TypeScript: TSConfig Option - emitDeclarationOnly(Official Docs)
- ๐
- ๐