How to fix Class decorator must be used on a class declaration in TypeScript

TypeScriptINTERMEDIATEMEDIUMUpdated Dec 8, 2025· 104 views

This error occurs when you attempt to apply a TypeScript class decorator to something other than a class declaration, such as a class expression, interface, type alias, or ambient context. Class decorators can only be used with concrete class declarations and have strict placement requirements in TypeScript.

Quick fix

Fixes Class decorator must be used on a class declaration

@Logger
const MyClass = class {
  name = "MyClass";
};
  1. Convert class expressions to class declarations
  2. Fix exported class expressions
  3. Enable experimentalDecorators in tsconfig.json
  4. Move class definitions out of functions
typescript — error
@Logger
const MyClass = class {
name = "MyClass";
};
Class decorator must be used on a class declaration

What this error means

This error reflects TypeScript's strict requirements for class decorators. A class decorator is a special TypeScript feature that allows you to augment or modify a class at compile time. However, decorators are only valid when applied directly to a class declaration—the statement that starts with the `class` keyword followed by the class name and body. The error occurs because TypeScript needs to apply the decorator to a concrete, statically-analyzable class definition. Class expressions (even named ones), interfaces, type aliases, abstract classes in declaration files, and classes in other ambient contexts don't provide the same level of compile-time certainty that decorators require. Additionally, decorators in class expressions are fundamentally incompatible with how TypeScript's decorator system works, as class expressions are evaluated at runtime as values, while decorators operate at the type level. This limitation is by design and applies to all TypeScript decorator targets: while method decorators, property decorators, and parameter decorators have their own restrictions, class decorators have the strictest placement requirement of all.

Typical symptoms

  • TypeScript compiler error explicitly mentioning "Class decorator must be used on a class declaration"
  • Error appears when trying to apply a decorator to a class expression or anonymous class
  • Decorator works fine on one class but fails on another when used in different contexts
  • Class expression assigned to a variable shows decorator error even though it looks like a class
  • Error occurs when applying decorators to classes inside functions or closures
  • Decorator fails when applied to exported class expressions or default exports of classes
  • Build succeeds in development but fails during production TypeScript compilation

Common causes

  1. Applying a decorator to a class expression instead of a class declaration
  2. Using decorators on exported class expressions (e.g., `export const MyClass = class {...}`)
  3. Attempting to apply decorators in a declare class or other ambient context
  4. Trying to use decorators on classes defined inside functions or conditional blocks
  5. Applying decorators to interfaces or type aliases instead of concrete classes
  6. Using decorators on anonymous classes returned from functions (mixin patterns)
  7. Forgetting to enable experimentalDecorators in tsconfig.json compiler options

How to fix "Class decorator must be used on a class declaration"

1Convert class expressions to class declarations

The most common cause is using a class expression instead of a class declaration. Move the class outside any expression context and define it as a standalone statement.

Bad - Class expression with decorator:

typescript
@Logger
const MyClass = class {
  name = "MyClass";
};

Good - Class declaration with decorator:

typescript
@Logger
class MyClass {
  name = "MyClass";
}

The key difference is that class MyClass { } is a declaration, while const MyClass = class { } is an expression assigned to a variable. TypeScript decorators only work with the declaration syntax.

2Fix exported class expressions

If you're exporting a class as an expression, convert it to a declaration before applying the decorator.

Bad - Exporting class expression with decorator:

typescript
@Logger
export const MyClass = class {
  getData() {
    return "data";
  }
};

Good - Exporting class declaration with decorator:

typescript
@Logger
class MyClass {
  getData() {
    return "data";
  }
}

export default MyClass;
// OR
export { MyClass };

You can still export the decorated class normally; just make sure the decorator is applied to the declaration, not the expression.

3Enable experimentalDecorators in tsconfig.json

Ensure that decorators are enabled in your TypeScript configuration. Even though modern TypeScript treats decorators as default syntax for declarations, you may need to explicitly enable experimental support depending on your setup.

tsconfig.json:

json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

The experimentalDecorators option enables decorator syntax, and emitDecoratorMetadata allows libraries like NestJS and TypeORM to use reflection metadata. After changing tsconfig.json, restart your TypeScript server or IDE.

4Move class definitions out of functions

If you're defining a class inside a function or trying to apply decorators to classes in conditional contexts, move the class to the module level.

Bad - Class defined inside function with decorator:

typescript
function createClass() {
  @Logger  // ❌ Decorator in function context
  class MyClass {
    value = 42;
  }
  return MyClass;
}

Good - Class at module level:

typescript
@Logger
class MyClass {
  value = 42;
}

function createClass() {
  return MyClass;
}

If you need dynamic class creation, consider using factory functions that return instances of pre-declared decorated classes instead of defining new classes conditionally.

5Avoid decorators on interfaces and type aliases

Decorators cannot be applied to interfaces or type aliases because they don't exist at runtime. Use concrete class declarations instead.

Bad - Decorator on interface:

typescript
@Logger  // ❌ Interfaces don't support decorators
interface IMyClass {
  getData(): string;
}

Bad - Decorator on type:

typescript
@Logger  // ❌ Types don't support decorators
type MyType = {
  name: string;
};

Good - Use a class instead:

typescript
@Logger
class MyClass {
  name: string;
  
  getData(): string {
    return this.name;
  }
}

If you only need the interface for type checking, use both: a decorated class and an interface that extends it or documents its contract.

6Refactor mixin patterns to use decorated base classes

If you're trying to use decorators with mixins (returning class expressions from functions), refactor to apply decorators to the concrete class instead.

Bad - Decorator on mixin pattern:

typescript
function applyTimestamp<T extends { new(...args: any[]): {} }>(Base: T) {
  @Logger  // ❌ Cannot decorate the return value
  return class extends Base {
    timestamp = new Date();
  };
}

Good - Declare and decorate the final class:

typescript
// Create the class separately
class TimestampedClass extends BaseClass {
  timestamp = new Date();
}

// Then decorate it
@Logger
class MyClass extends TimestampedClass {
  name = "MyClass";
}

Alternatively, use factory functions that return instances of properly decorated classes.

7Check for TypeScript ambient contexts

Decorators cannot be used in declare statements or .d.ts files. If you're working in a declaration file, move the decorated class to a regular .ts implementation file.

Bad - Decorator in .d.ts file:

typescript
// types.d.ts
@Logger  // ❌ Cannot use decorators in declaration files
declare class MyClass {
  getData(): string;
}

Good - Implementation in .ts file:

typescript
// myclass.ts
@Logger
class MyClass {
  getData(): string {
    return "data";
  }
}

export { MyClass };

Declaration files are for type information only and don't execute decorators. Keep decorated classes in implementation files and export their types as needed.

Advanced notes

TypeScript decorators operate at the type system level and require static analyzability. This is why class expressions—even when assigned to constants—aren't supported. The decorators specification and TypeScript's implementation both assume that decorators are applied to declarations that exist in the abstract syntax tree as distinct statements, not as expressions.

The strict class declaration requirement also applies to abstract classes defined in ambient contexts (declare abstract class). If you need to decorate an abstract class, it must be a real implementation, not a declaration file definition.

When working with frameworks like NestJS, Angular, or TypeORM that heavily rely on decorators, remember that all your service classes, controller classes, and entity classes must be declared as class declarations, not expressions. This affects patterns like exporting anonymous classes or using class expressions as mixins.

If you're migrating from other languages with more flexible decorator systems, note that TypeScript's restriction is intentional—it enables better tooling, type safety, and predictable behavior. Modern TypeScript (5.0+) has relaxed some experimental restrictions but still maintains the class declaration requirement for class decorators. Always apply decorators immediately before the class keyword in the source code.

For testing scenarios, if you need to create test doubles of decorated classes, create proper subclasses that extend the decorated class rather than trying to apply decorators dynamically at runtime.

Frequently asked questions

What does "Class decorator must be used on a class declaration" mean?
This error reflects TypeScript's strict requirements for class decorators. A class decorator is a special TypeScript feature that allows you to augment or modify a class at compile time. However, decorators are only valid when applied directly to a class declaration—the statement that starts with the class keyword followed by the class name and body.
How do I fix "Class decorator must be used on a class declaration"?
This error occurs when you attempt to apply a TypeScript class decorator to something other than a class declaration, such as a class expression, interface, type alias, or ambient context. Class decorators can only be used with concrete class declarations and have strict placement requirements in TypeScript.
What causes "Class decorator must be used on a class declaration"?
Applying a decorator to a class expression instead of a class declaration Using decorators on exported class expressions (e.g., export const MyClass = class {...}) Attempting to apply decorators in a declare class or other ambient context
Is the "Class decorator must be used on a class declaration" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading