Skip to content

Angular NG2007 Error: Fixing "Class is using Angular features but is not decorated"

Problem Statement

When creating a base class that contains Angular-specific features like @Input() decorators and extending this class in your Angular components, you may encounter the following error:

ERROR: Class is using Angular features but is not decorated. Please add an explicit Angular decorator.

This occurs when:

  • You have a base class with Angular decorators like @Input(), @Output(), or @ViewChild()
  • Your derived components extend this base class
  • The base class itself lacks an Angular decorator

Solution: Adding an Appropriate Decorator

Use the @Directive() decorator for your base class:

typescript
import { Directive, Input } from '@angular/core';

@Directive()
export abstract class BaseComponent {
    @Input() teamName: string;
    @Input() teamSize: number;
    @Input() players: any;
}

This approach:

  • Doesn't require dependency injection compatibility
  • Clearly indicates the class serves as a base for components/directives
  • Follows Angular's official migration guidance

For Component-Specific Base Classes

If your base class needs component-specific functionality, use @Component():

typescript
import { Component, Input } from '@angular/core';

@Component({
  template: ''
})
export abstract class BaseComponent {
    @Input() teamName: string;
    @Input() teamSize: number;
    @Input() players: any;
}

WARNING

Using @Component() requires that all constructor arguments be resolvable through Angular's dependency injection system.

Alternative: Using @Injectable()

You can also use @Injectable() as an alternative:

typescript
import { Injectable, Input } from '@angular/core';

@Injectable()
export abstract class BaseComponent {
    @Input() teamName: string;
    @Input() teamSize: number;
    @Input() players: any;
}

Implementation Example

Here's how to properly structure your components:

Base Component

typescript
import { Directive, Input } from '@angular/core';

@Directive()
export abstract class BaseComponent {
    @Input() teamName: string;
    @Input() teamSize: number;
    @Input() players: any[];
    
    // Common methods can be defined here
    getPlayerCount(): number {
        return this.players?.length || 0;
    }
}

Derived Component

typescript
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-cricket',
  templateUrl: './cricket.component.html',
  styleUrls: ['./cricket.component.scss']
})
export class CricketComponent extends BaseComponent implements OnInit {

  constructor() {
    super();
  }

  ngOnInit(): void {
    // Component-specific initialization
  }
  
  // Component-specific methods
}

Additional Considerations

TypeScript Version Compatibility

If you're using Angular 15+, ensure you're using a compatible TypeScript version:

bash
npm install typescript@4.8.2 --save-dev --save-exact

Code Organization

Ensure your class definitions are properly positioned in your files:

typescript
// Correct: Base class defined before component
export class HelperClass {
  // Helper implementation
}

@Component({
  selector: 'app-example',
  template: '<div>Example</div>'
})
export class ExampleComponent {
  // Component implementation
}

// Also acceptable: Base class defined after component

INFO

This error was introduced in Angular 10 as part of the Ivy compiler's stricter checking for undecorated base classes that use Angular features.

Best Practices

  1. Always mark base classes as abstract to prevent direct instantiation
  2. Use @Directive() instead of @Component() when no template is needed
  3. Keep base classes focused on common functionality only
  4. Follow Angular's migration guide for undecorated classes

By properly decorating your base classes, you'll resolve the NG2007 error while maintaining a clean, maintainable component architecture.