How to fix Option 'allowImportingTsExtensions' can only be used when either 'noEmit' or 'emitDeclarationOnly' is set. in TypeScript
This error occurs when you enable TypeScript's 'allowImportingTsExtensions' option without also enabling 'noEmit' or 'emitDeclarationOnly'. The fix depends on whether you're using a bundler or TypeScript runtime.
Quick fix
Fixes TS6302
{
"compilerOptions": {
"allowImportingTsExtensions": true,
"noEmit": true
}
}- Understand your build setup (bundler vs runtime vs pure TypeScript)
- Enable 'noEmit' in tsconfig.json
- Alternatively, use 'emitDeclarationOnly' for declaration files
- Use 'rewriteRelativeImportExtensions' to emit JavaScript
{"compilerOptions": {"allowImportingTsExtensions": true,"noEmit": true}}Option 'allowImportingTsExtensions' can only be used when either 'noEmit' or 'emitDeclarationOnly' is set.
What this error means
TypeScript's `allowImportingTsExtensions` option allows importing files with TypeScript-specific extensions like `.ts`, `.mts`, or `.tsx` directly in your source code. However, TypeScript enforces that this option can only be used when `noEmit` or `emitDeclarationOnly` is enabled. This restriction exists because: 1. **Import paths aren't rewritten**: When TypeScript emits JavaScript, it doesn't automatically rewrite `.ts` extensions to `.js` 2. **Runtime incompatibility**: If your compiled JavaScript output contains `import "./file.ts"`, that import will fail at runtime because Node.js, browsers, and other JavaScript runtimes cannot execute `.ts` files directly 3. **Prevents invalid output**: The restriction prevents you from accidentally generating unrunnable JavaScript code The error typically appears when using modern TypeScript setup with a bundler (Webpack, Vite, esbuild) or a TypeScript runtime (tsx, ts-node, Deno, Bun) without proper configuration.
Typical symptoms
- TypeScript compilation fails with TS5096 error message
- Error appears immediately when running `tsc` or `tsc --noEmit`
- Build tools report the TypeScript error during type-checking
- The error happens even after adding `allowImportingTsExtensions: true`
- Your bundler or test runner still won't compile your project
Common causes
- You have 'allowImportingTsExtensions' enabled but 'noEmit' is false or missing (most common)
- You enabled 'allowImportingTsExtensions' for a project that emits JavaScript files
- Your build tool configuration doesn't match TypeScript's compiler options
- You're using a bundler but haven't disabled TypeScript's own emission
- TypeScript version mismatch between expected and installed version
How to fix "Option 'allowImportingTsExtensions' can only be used when either 'noEmit' or 'emitDeclarationOnly' is set."
First, determine what you're actually using to run/build your code:
If you're using a bundler (Webpack, Vite, esbuild, Parcel):
Your bundler handles TypeScript transpilation, not TypeScript itself.
If you're using a TypeScript runtime (tsx, ts-node, Deno, Bun):
These runtimes execute TypeScript files directly without emitting JavaScript.
If you're using pure TypeScript compilation (tsc):
TypeScript itself emits the JavaScript files.
Understanding this helps determine the right fix.
Add or update the noEmit compiler option in your tsconfig.json:
{
"compilerOptions": {
"allowImportingTsExtensions": true,
"noEmit": true
}
}noEmit: true tells TypeScript to skip emitting JavaScript entirely. This is appropriate when:
- You're using a bundler to handle transpilation
- You're using a TypeScript runtime (tsx, ts-node, Deno, Bun)
- You only want TypeScript for type-checking
If you need to emit declaration files (.d.ts) but not JavaScript, use:
{
"compilerOptions": {
"allowImportingTsExtensions": true,
"emitDeclarationOnly": true
}
}This is useful for:
- Publishing a library with TypeScript definitions
- Pre-generating type definitions for your bundled code
- Type-only outputs
If you actually need to emit JavaScript files AND use .ts extensions in imports, use rewriteRelativeImportExtensions (TypeScript 5.7+):
{
"compilerOptions": {
"allowImportingTsExtensions": true,
"rewriteRelativeImportExtensions": true,
"module": "esnext",
"moduleResolution": "bundler"
}
}This tells TypeScript to automatically rewrite .ts imports to .js in the emitted output, making the generated JavaScript valid for runtime execution.
Requirements:
- TypeScript 5.7+
- Must use "esnext" or compatible module format
- Use "bundler" or "node" for moduleResolution
If using a bundler, ensure it's configured to handle TypeScript:
Vite:
// vite.config.ts
export default {
esbuild: {
target: 'esnext'
}
}Webpack:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader'
}
]
}
}esbuild:
import * as esbuild from 'esbuild';
await esbuild.build({
entryPoints: ['src/index.ts'],
outdir: 'dist',
format: 'esm'
});Once configured, test your build:
# With noEmit enabled (type-checking only)
npx tsc --noEmit
# Or run your bundler/runtime
npm run dev
npm run build
tsx src/index.tsThe error should disappear. Your .ts imports should now work correctly.
Advanced notes
### TypeScript 6.0 Preview
TypeScript 6.0 (planned future release) will make allowImportingTsExtensions the default behavior, removing the need for explicit configuration. This change recognizes that most modern TypeScript projects use bundlers or runtimes that handle TypeScript natively.
### Using with Different TypeScript Runtimes
tsx:
# No tsconfig.json changes needed if using tsx
tsx src/index.tsts-node:
// tsconfig.json
{
"compilerOptions": {
"noEmit": false,
"allowImportingTsExtensions": true,
"esModuleInterop": true
},
"ts-node": {
"esm": true
}
}Deno:
# Deno handles this automatically
deno run --allow-all src/index.tsBun:
# Bun handles this automatically
bun src/index.ts### When NOT to Use allowImportingTsExtensions
If you're building a library that will be consumed by JavaScript users, avoid .ts extensions in your public API. Stick to .js or standard package exports. Only use .ts extensions in:
- Internal/private code
- Type-only imports
- Tools that will be run with a TypeScript runtime
### CJS vs ESM Considerations
The error is more common in ESM projects. If you're using CommonJS, the configuration differs:
{
"compilerOptions": {
"allowImportingTsExtensions": true,
"noEmit": true,
"module": "commonjs",
"moduleResolution": "node"
}
}Frequently asked questions
- What does "TS6302" mean?
- tsx directly in your source code. However, TypeScript enforces that this option can only be used when noEmit or emitDeclarationOnly is enabled. This restriction exists because: 1.
- How do I fix "TS6302"?
- This error occurs when you enable TypeScript's 'allowImportingTsExtensions' option without also enabling 'noEmit' or 'emitDeclarationOnly'. The fix depends on whether you're using a bundler or TypeScript runtime.
- What causes "TS6302"?
- You have 'allowImportingTsExtensions' enabled but 'noEmit' is false or missing (most common) You enabled 'allowImportingTsExtensions' for a project that emits JavaScript files Your build tool configuration doesn't match TypeScript's compiler options
- Is the "TS6302" error serious?
- It is a low-severity error โ more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- ๐TypeScript Official Documentation
- ๐
- ๐TypeScript: TSConfig Option - noEmit (Official Docs)(Official Docs)
- ๐TypeScript: TSConfig Reference (Official Docs)(Official Docs)
- ๐
- ๐
- ๐