How to fix ts-node does not support 'emitDecoratorMetadata' without 'experimentalDecorators' in TypeScript

TypeScriptINTERMEDIATEMEDIUMUpdated Dec 11, 2025· 141 views

This error occurs when using ts-node with decorators in TypeScript. The emitDecoratorMetadata compiler option requires experimentalDecorators to be enabled first. The fix involves updating your tsconfig.json to enable both options or adjusting your TypeScript configuration to properly support decorator metadata emission.

Quick fix

Fixes ts-node does not support 'emitDecoratorMetadata' without 'experimentalDecorators'

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    // Other compiler options...
    "target": "ES2022",
    "module": "commonjs",
    "strict": true
  }
}
  1. Enable experimentalDecorators in tsconfig.json
  2. Verify ts-node is using the correct tsconfig
  3. Check command-line TypeScript flags
  4. Update ts-node and TypeScript versions
typescript — error
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
// Other compiler options...
"target": "ES2022",
"module": "commonjs",
"strict": true
}
}
ts-node does not support 'emitDecoratorMetadata' without 'experimentalDecorators'

What this error means

The error "ts-node does not support 'emitDecoratorMetadata' without 'experimentalDecorators'" appears when you're using ts-node to run TypeScript code that uses decorators with metadata emission. This is a configuration issue where your TypeScript compiler options are incomplete or inconsistent. TypeScript's decorator system has two related options: 1. **experimentalDecorators**: Enables decorator syntax support (required for using decorators) 2. **emitDecoratorMetadata**: Emits design-time type metadata for decorators (requires experimentalDecorators to be enabled first) The error occurs because ts-node validates that these options are properly configured before attempting to compile and run your code. When emitDecoratorMetadata is set to true but experimentalDecorators is false or not set, ts-node rejects the configuration as invalid. This is particularly common in frameworks like NestJS, TypeORM, or class-validator that rely on decorator metadata for dependency injection, validation, or ORM mapping. The metadata includes type information that's needed at runtime for these frameworks to work properly.

Typical symptoms

  • ts-node fails with error: 'ts-node does not support 'emitDecoratorMetadata' without 'experimentalDecorators''
  • Running TypeScript files with ts-node results in immediate failure
  • Node.js applications using decorators fail to start when using ts-node
  • Frameworks like NestJS, TypeORM, or class-validator fail to initialize
  • Error occurs even before your application code executes
  • The same code may work with tsc compilation but fails with ts-node execution

Common causes

  1. tsconfig.json has emitDecoratorMetadata: true but experimentalDecorators is false or missing
  2. Multiple tsconfig files with conflicting compiler options
  3. Command-line TypeScript flags override tsconfig.json settings incorrectly
  4. Using a framework template that hasn't properly configured both decorator options
  5. Recent TypeScript or ts-node version update changed default behavior
  6. Project configuration files (like nest-cli.json) not properly synchronized with tsconfig.json

How to fix "ts-node does not support 'emitDecoratorMetadata' without 'experimentalDecorators'"

1Enable experimentalDecorators in tsconfig.json

First, ensure both experimentalDecorators and emitDecoratorMetadata are properly set in your tsconfig.json:

json
{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    // Other compiler options...
    "target": "ES2022",
    "module": "commonjs",
    "strict": true
  }
}

The order doesn't matter, but both must be present and experimentalDecorators must be true when emitDecoratorMetadata is true.

If you're using a framework like NestJS, check the framework's default tsconfig.json:

bash
# For NestJS projects
cat tsconfig.json | grep -A2 -B2 "experimentalDecorators"
cat tsconfig.json | grep -A2 -B2 "emitDecoratorMetadata"

After updating tsconfig.json, restart your ts-node process.

2Verify ts-node is using the correct tsconfig

ts-node may be using a different tsconfig file than you expect. Check which configuration file is being loaded:

bash
# Run with --show-config to see what ts-node is using
npx ts-node --show-config

# Or specify the tsconfig explicitly
npx ts-node -P tsconfig.json your-file.ts

# For projects with multiple configs (like tsconfig.build.json)
npx ts-node -P tsconfig.build.json your-file.ts

If you have multiple tsconfig files, ensure consistency:

json
// tsconfig.json (development)
{
  "extends": "./tsconfig.base.json",
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

// tsconfig.build.json (production)
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Always check that all extended configurations have the required options.

3Check command-line TypeScript flags

Command-line flags can override tsconfig.json settings. Verify your package.json scripts or execution commands:

json
// package.json - WRONG example
{
  "scripts": {
    "start": "ts-node --compiler-options '{"emitDecoratorMetadata":true}' src/main.ts"
  }
}

The above is missing experimentalDecorators. Use either:

json
// Option 1: Specify both options
{
  "scripts": {
    "start": "ts-node --compiler-options '{"experimentalDecorators":true,"emitDecoratorMetadata":true}' src/main.ts"
  }
}

// Option 2: Use tsconfig.json (recommended)
{
  "scripts": {
    "start": "ts-node -P tsconfig.json src/main.ts"
  }
}

For frameworks with custom CLI tools (like NestJS):

bash
# Check nest-cli.json configuration
cat nest-cli.json

# Ensure it references the correct tsconfig
{
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
    "tsConfigPath": "tsconfig.json"
  }
}
4Update ts-node and TypeScript versions

Older versions of ts-node or TypeScript may have different behavior. Update to compatible versions:

bash
# Check current versions
npx ts-node --version
npx tsc --version

# Update packages
npm install --save-dev typescript@latest ts-node@latest

# Or update with specific versions
npm install --save-dev typescript@5.3.0 ts-node@10.9.0

Version compatibility matrix:
- TypeScript 5.x works with ts-node 10.x
- TypeScript 4.x works with ts-node 9.x or 10.x
- Avoid mixing major version mismatches

If updating doesn't help, try clearing npm cache and reinstalling:

bash
npm cache clean --force
rm -rf node_modules package-lock.json
npm install
5Configure ts-node programmatically

For advanced use cases, configure ts-node programmatically in your entry file:

typescript
// register.ts or main.ts
import { register } from 'ts-node';

register({
  compilerOptions: {
    experimentalDecorators: true,
    emitDecoratorMetadata: true,
    target: 'ES2022',
    module: 'commonjs'
  }
});

// Now import your application
import { AppModule } from './app.module';
// ... rest of your code

Or use ts-node/register with require:

javascript
// In your main JavaScript file
require('ts-node').register({
  compilerOptions: {
    experimentalDecorators: true,
    emitDecoratorMetadata: true
  }
});

require('./src/main.ts');

For Jest testing with ts-jest:

javascript
// jest.config.js
module.exports = {
  preset: 'ts-jest',
  globals: {
    'ts-jest': {
      tsconfig: {
        experimentalDecorators: true,
        emitDecoratorMetadata: true
      }
    }
  }
};
6Alternative: Use tsc compilation instead of ts-node

If ts-node continues to have issues, consider compiling with tsc first, then running the JavaScript:

bash
# Compile TypeScript to JavaScript
npx tsc

# Run the compiled JavaScript
node dist/main.js

Or use a build process with watch mode:

json
{
  "scripts": {
    "build": "tsc",
    "start": "node dist/main.js",
    "dev": "concurrently "tsc --watch" "nodemon dist/main.js""
  }
}

Install required packages:

bash
npm install --save-dev concurrently nodemon

For development with hot reload, consider ts-node-dev:

bash
npm install --save-dev ts-node-dev
json
{
  "scripts": {
    "dev": "ts-node-dev --respawn --transpile-only src/main.ts"
  }
}

ts-node-dev automatically handles tsconfig.json and may have different error handling.

Advanced notes

### Understanding Decorator Metadata

When emitDecoratorMetadata is enabled, TypeScript emits type metadata that can be accessed at runtime using the reflect-metadata library:

typescript
import 'reflect-metadata';

class Example {
  constructor(@Inject() private service: Service) {}
}

// At runtime, you can access:
const paramTypes = Reflect.getMetadata('design:paramtypes', Example);
// Returns [Service] - the type information

This metadata is used by:
- NestJS: For dependency injection (determining what to inject)
- TypeORM: For mapping TypeScript types to database columns
- class-validator: For validation rules based on type information
- class-transformer: For object transformation

### TypeScript 5.0+ and Decorators

TypeScript 5.0 introduced changes to decorators that may affect this error:

1. New decorators proposal: TypeScript 5.0+ supports both old (experimental) and new (standard) decorators
2. Metadata emission differences: New decorators may have different metadata behavior
3. Configuration: For new decorators, use "experimentalDecorators": false and enable via "useDefineForClassFields"

json
{
  "compilerOptions": {
    "target": "ES2022",
    "useDefineForClassFields": true,
    "experimentalDecorators": false,
    "emitDecoratorMetadata": false  // May not be supported with new decorators
  }
}

### Framework-Specific Considerations

NestJS:
- Requires both options enabled
- Uses reflect-metadata polyfill
- Check nest-cli.json for compiler options overrides

TypeORM:
- Needs metadata for entity column types
- Works with both experimental and new decorators (in newer versions)
- May require additional reflect-metadata configuration

Angular:
- Uses its own decorator system (not TypeScript's experimentalDecorators)
- Angular CLI manages tsconfig.json automatically
- Rarely encounters this specific ts-node error

### Debugging ts-node Configuration

To debug what ts-node is seeing:

bash
# Show full configuration
TS_NODE_DEBUG=true npx ts-node --show-config your-file.ts

# Check environment variables affecting ts-node
env | grep TS_NODE

# Common environment variables:
# TS_NODE_COMPILER_OPTIONS - JSON string of compiler options
# TS_NODE_PROJECT - Path to tsconfig.json
# TS_NODE_FILES - Whether to include files from tsconfig

### Performance Considerations

emitDecoratorMetadata increases bundle size and may affect compilation performance. Consider disabling it in production if not needed:

json
// tsconfig.build.json (production)
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "emitDecoratorMetadata": false  // Disable for smaller bundles
  }
}

However, frameworks requiring metadata (like NestJS) won't work without it.

### Migration from JavaScript Decorators

If migrating from Babel or other transpilers that handled decorators differently:

1. Ensure reflect-metadata is installed: npm install reflect-metadata
2. Import it at the entry point: import 'reflect-metadata';
3. Verify tsconfig.json matches your previous decorator transformation settings
4. Test that runtime metadata access works as expected

Frequently asked questions

What does "ts-node does not support 'emitDecoratorMetadata' without 'experimental" mean?
The error "ts-node does not support 'emitDecoratorMetadata' without 'experimentalDecorators'" appears when you're using ts-node to run TypeScript code that uses decorators with metadata emission. This is a configuration issue where your TypeScript compiler options are incomplete or inconsistent. TypeScript's decorator system has two related options: 1.
How do I fix "ts-node does not support 'emitDecoratorMetadata' without 'experimental"?
This error occurs when using ts-node with decorators in TypeScript. The emitDecoratorMetadata compiler option requires experimentalDecorators to be enabled first. The fix involves updating your tsconfig.json to enable both options or adjusting your TypeScript configuration to properly support decorator metadata emission.
What causes "ts-node does not support 'emitDecoratorMetadata' without 'experimental"?
tsconfig.json has emitDecoratorMetadata: true but experimentalDecorators is false or missing Multiple tsconfig files with conflicting compiler options Command-line TypeScript flags override tsconfig.json settings incorrectly
Is the "ts-node does not support 'emitDecoratorMetadata' without 'experimental" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading