How to fix Decorators are not valid here in TypeScript
This TypeScript error occurs when decorators are used in unsupported locations, such as class expressions, anonymous classes, nested classes, or standalone functions. The fix involves moving decorators to supported declarations like top-level classes, methods, properties, or parameters.
Quick fix
Fixes TS1206
// WRONG - decorator on class expression
const MyClass = @Component({
selector: 'app-root'
})
class { }
// Error: Decorators are not valid here
// CORRECT - decorator on class declaration
@Component({
selector: 'app-root'
})
class MyClass { }
// Or if you need the variable assignment
@Component({
selector: 'app-root'
})
class MyClassDeclaration { }
const MyClass = MyClassDeclaration;- Convert class expressions to class declarations
- Extract nested classes to top level
- Refactor mixin patterns to avoid decorators on anonymous classes
- Fix instantiated class exports
// WRONG - decorator on class expressionconst MyClass = @Component({selector: 'app-root'})class { }// Error: Decorators are not valid here// CORRECT - decorator on class declaration@Component({selector: 'app-root'})class MyClass { }// Or if you need the variable assignment@Component({selector: 'app-root'})class MyClassDeclaration { }const MyClass = MyClassDeclaration;Decorators are not valid here
What this error means
The "Decorators are not valid here" error (TS1206) appears when you attempt to use a decorator in a syntactic context where TypeScript does not allow decorators. Decorators are special declarations that can modify classes, methods, accessors, properties, or parameters, but they have strict placement rules. TypeScript decorators must be attached to specific declaration types at the top level of their scope. They cannot be used with class expressions, classes nested inside objects, anonymous classes returned from functions, standalone functions, or interface/type definitions. This error commonly occurs when: 1. **Class expressions**: Attempting to decorate a class expression assigned to a variable or returned from a function 2. **Nested classes**: Using decorators on classes defined inside objects or other non-standard locations 3. **Anonymous classes**: Decorating classes in contexts like mixins where the class is anonymous 4. **Invalid targets**: Applying decorators to constructs that don't support them (functions, interfaces, types)
Typical symptoms
- Compilation fails with 'Decorators are not valid here' error message
- Error code TS1206 appears in TypeScript compiler output
- IDE shows red underlines beneath decorator syntax (@decorator)
- Decorators on class expressions or nested classes trigger the error
- Code works without decorators but fails when adding them
- Error occurs when using decorators in mixin patterns or factory functions
Common causes
- Using decorators on class expressions (e.g., const MyClass = @decorator class { })
- Applying decorators to classes nested inside objects or returned from functions
- Decorating anonymous classes in mixin patterns or factory functions
- Attempting to use decorators on standalone functions (not methods)
- Placing decorators on interface or type definitions
- Using decorators inside instantiated class exports (export default new class)
- Decorating non-top-level class declarations
How to fix "Decorators are not valid here"
The most common cause is using decorators on class expressions. Convert them to proper class declarations:
// WRONG - decorator on class expression
const MyClass = @Component({
selector: 'app-root'
})
class { }
// Error: Decorators are not valid here
// CORRECT - decorator on class declaration
@Component({
selector: 'app-root'
})
class MyClass { }
// Or if you need the variable assignment
@Component({
selector: 'app-root'
})
class MyClassDeclaration { }
const MyClass = MyClassDeclaration;For exported classes:
// WRONG - class expression with decorator
export const AppComponent = @Component({
selector: 'app-root'
})
class { }
// CORRECT - declare class first, then export
@Component({
selector: 'app-root'
})
export class AppComponent { }Decorators cannot be used on classes nested inside objects or functions. Move them to module scope:
// WRONG - decorator on nested class
const services = {
UserService: @Injectable()
class {
getUser() { }
}
};
// Error: Decorators are not valid here
// CORRECT - extract to top level
@Injectable()
class UserService {
getUser() { }
}
const services = {
UserService
};For classes returned from functions:
// WRONG - decorator on anonymous returned class
function createService() {
return @Injectable()
class {
getData() { }
};
}
// CORRECT - declare class with name first
@Injectable()
class DataService {
getData() { }
}
function createService() {
return DataService;
}If you're using decorators in mixin patterns, refactor to apply decorators after class creation:
// WRONG - decorator on anonymous class in mixin
const TimestampMixin = (Base: any) => {
return @Entity()
class extends Base {
@Column()
createdAt: Date;
};
};
// Error: Decorators are not valid here on the inner class
// CORRECT - declare named class
const TimestampMixin = (Base: any) => {
@Entity()
class Timestamped extends Base {
@Column()
createdAt: Date;
}
return Timestamped;
};Alternative approach using a factory decorator:
// Apply decorator to the final composed class
function applyTimestamp<T extends { new(...args: any[]): {} }>(Base: T) {
return class extends Base {
createdAt: Date = new Date();
};
}
@Entity()
class User extends applyTimestamp(BaseEntity) {
@Column()
name: string;
}A common pattern that causes this error is exporting an instance of a decorated class:
// WRONG - decorator on instantiated class
export default new @Singleton()
class ApiClient {
@Log()
fetch() { }
}
// Error: Decorators are not valid here
// CORRECT - declare class separately, then instantiate
@Singleton()
class ApiClient {
@Log()
fetch() { }
}
export default new ApiClient();For singleton patterns:
// Declare decorated class
@Injectable()
class ConfigService {
private config: Config;
@Cache()
getConfig() {
return this.config;
}
}
// Export instance separately
export const configService = new ConfigService();If you're using legacy decorators (pre-TypeScript 5.0), ensure the compiler option is set:
// tsconfig.json
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true // Often needed with DI frameworks
}
}For TypeScript 5.0+ with stage 3 decorators (no flag needed):
// tsconfig.json - stage 3 decorators work without flag
{
"compilerOptions": {
"target": "ES2022",
// experimentalDecorators is NOT needed for stage 3 decorators
}
}Note: If migrating from legacy to stage 3 decorators, syntax and behavior differ. Check your framework's documentation for compatibility.
Decorators can only be applied to specific targets. Ensure you're using them correctly:
// VALID decorator targets:
// 1. Class declarations
@Component()
class MyComponent { }
// 2. Class methods
class Service {
@Log()
fetchData() { }
}
// 3. Class properties
class User {
@Column()
name: string;
}
// 4. Method parameters
class Controller {
create(@Body() dto: CreateDto) { }
}
// 5. Accessors (getters/setters)
class Person {
@Validate()
get age() { return this._age; }
}// INVALID decorator targets:
// Standalone functions - NOT SUPPORTED
@Log() // Error
function fetchData() { }
// Interfaces - NOT SUPPORTED
@Entity() // Error
interface User { }
// Type aliases - NOT SUPPORTED
@Serializable() // Error
type Config = { };Advanced notes
### Decorator Evaluation Order
When multiple decorators are applied to a single declaration, TypeScript evaluates them in a specific order:
Expression evaluation (top to bottom):
@first() // Evaluated first
@second() // Evaluated second
@third() // Evaluated third
class Example { }Function execution (bottom to top):
The decorator functions are called in reverse order: third() → second() → first()
Within a class:
1. Parameter decorators, then method/accessor/property decorators for each instance member
2. Parameter decorators, then method/accessor/property decorators for each static member
3. Parameter decorators for the constructor
4. Class decorators for the class
### Legacy vs Stage 3 Decorators
TypeScript supports two decorator implementations:
Legacy Decorators (experimentalDecorators)
Used by Angular, NestJS, TypeORM (pre-2024):
// tsconfig.json
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
// Decorator implementation
function Log(target: any, propertyKey: string) {
// Legacy decorator signature
}Stage 3 Decorators (TypeScript 5.0+)
ECMAScript standard decorators with different API:
// No compiler flag needed
// Decorator implementation
function Log(target: Function, context: ClassMethodDecoratorContext) {
// Stage 3 decorator signature
}These are NOT compatible. If you see "Decorators are not valid here" after upgrading TypeScript, your framework may need to update for stage 3 support.
### Decorator Factories
To create configurable decorators, use decorator factories (functions that return decorators):
// Decorator factory
function Component(config: { selector: string }) {
return function (target: Function) {
// Actual decorator logic
target.prototype.selector = config.selector;
};
}
// Usage - note the function call ()
@Component({ selector: 'app-root' })
class AppComponent { }The @Component({ selector: 'app-root' }) syntax is actually:
1. Call Component() → returns a decorator function
2. Apply that decorator to the class
### Reflect Metadata API
Many decorator-based frameworks use metadata reflection:
import 'reflect-metadata';
function Type(type: any) {
return Reflect.metadata('design:type', type);
}
class User {
@Type(String)
name: string;
}
// Read metadata at runtime
const type = Reflect.getMetadata('design:type', User.prototype, 'name');
console.log(type); // [Function: String]Requires emitDecoratorMetadata: true and reflect-metadata package.
### Framework-Specific Patterns
Angular
// WRONG
export const AppComponent = @Component({ ... }) class { };
// CORRECT
@Component({ ... })
export class AppComponent { }NestJS
// WRONG
const UserController = @Controller('users') class { };
// CORRECT
@Controller('users')
export class UserController { }TypeORM
// WRONG
const UserEntity = @Entity() class { };
// CORRECT
@Entity()
export class User { }### Debugging Decorator Issues
Enable verbose compiler output to see exactly where decorators are being applied:
npx tsc --listEmittedFiles --listFilesCheck the emitted JavaScript to verify decorator transformation:
npx tsc --declaration --emitDecoratorMetadata
cat dist/your-file.jsFrequently asked questions
- What does "TS1206" mean?
- The "Decorators are not valid here" error (TS1206) appears when you attempt to use a decorator in a syntactic context where TypeScript does not allow decorators. Decorators are special declarations that can modify classes, methods, accessors, properties, or parameters, but they have strict placement rules. TypeScript decorators must be attached to specific declaration types at the top level of their scope.
- How do I fix "TS1206"?
- This TypeScript error occurs when decorators are used in unsupported locations, such as class expressions, anonymous classes, nested classes, or standalone functions. The fix involves moving decorators to supported declarations like top-level classes, methods, properties, or parameters.
- What causes "TS1206"?
- Using decorators on class expressions (e.g., const MyClass = @decorator class { }) Applying decorators to classes nested inside objects or returned from functions Decorating anonymous classes in mixin patterns or factory functions
- Is the "TS1206" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚TypeScript Official Documentation
- 📖TypeScript Handbook - Decorators(Official Docs)
- 📖TypeScript TSConfig - experimentalDecorators(Official Docs)
- 📖TypeScript 5.0 Release Notes - Stage 3 Decorators(Official Docs)
- 🐙
- 🐙
- 🐙
- 📖TC39 - ECMAScript Decorators Proposal(Official Docs)