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
For Angular 10+ (Recommended)
Use the @Directive()
decorator for your base class:
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()
:
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:
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
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
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:
npm install typescript@4.8.2 --save-dev --save-exact
Code Organization
Ensure your class definitions are properly positioned in your files:
// 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
- Always mark base classes as
abstract
to prevent direct instantiation - Use
@Directive()
instead of@Component()
when no template is needed - Keep base classes focused on common functionality only
- 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.