Skip to content

Angular: Class is using Angular features but is not decorated エラーの解決方法

この記事では、Angularコンポーネント開発で頻繁に遭遇する「Class is using Angular features but is not decorated. Please add an explicit Angular decorator」エラーの原因と解決策について詳しく解説します。

問題の概要

Angularアプリケーションで、複数のコンポーネントに共通するプロパティを基底クラスに定義し、それを継承する構造を実装した際に次のエラーが発生します:

ERROR in src/app/base-screen.ts:4:14 - error NG2007:
Class is using Angular features but is not decorated. Please add an explicit Angular decorator.

このエラーは、Angularの機能(例:@Input()デコレータ)を使用しているクラスが、Angularのデコレータ(@Component@Directiveなど)で修飾されていない場合に発生します。

エラーが発生するコード例

typescript
// BaseComponent.ts - 問題のあるコード
export class BaseComponent {
    @Input() TeamName: string;
    @Input() teamSize: number;
    @Input() players: any;
}

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

  ngOnInit(): void {
  }
}

解決方法

方法1: @Directiveデコレータの使用(推奨)

Angular 10以降では、@Directive()デコレータを使用するのが最も簡単で軽量な解決策です。

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

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

ポイント

  • @Directive()はDI互換性を要求しないため、コンストラクタ引数に定数やリテラルを使用できる利点があります
  • 基底クラスは実体化されないため、abstractキーワードを追加することを推奨します

方法2: @Componentデコレータの使用

Angular 9以前のバージョンでは、@Componentデコレータを使用する必要があります。

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

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

注意点

@Componentデコレータを使用する場合、テンプレートが必要ですが、空文字を指定することで回避できます。ただし、DI互換性が要求されるため、コンストラクタ引数には注意が必要です。

方法3: @Injectableデコレータの使用

サービスとしての機能も持たせる場合には@Injectableデコレータも使用できます。

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

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

その他の考慮事項

TypeScriptバージョンの互換性

Angular 15を使用している場合、TypeScriptのバージョン互換性問題が原因でこのエラーが発生することがあります。以下のコマンドでTypeScript 4.8.2をインストールすることで解決できる場合があります:

bash
npm i typescript@4.8.2 -D --save-exact

クラスの配置順序

複数のクラスを同じファイルに定義する場合、クラスの配置順序が重要です:

typescript
// 正しい順序: 使用されるクラスを先に定義
export class Y {
  // Yの実装
}

@Component({
  selector: 'app-x',
  templateUrl: './x.component.html',
  styleUrls: ['./x.component.css']
})
export class XComponent implements OnInit {
  // XComponentの実装(Yクラスを使用)
}

間違った順序

typescript
@Component({
  selector: 'app-x',
  templateUrl: './x.component.html',
  styleUrls: ['./x.component.css']
})
export class XComponent implements OnInit {
  // ここでYクラスを使用するが...
}

export class Y {
  // Yクラスは後で定義されている(エラーの原因)
}

まとめ

「Class is using Angular features but is not decorated」エラーは、Angularの機能を使用するクラスに適切なデコレータが付与されていない場合に発生します。解決策としては:

  1. Angular 10+: @Directive()デコレータの使用が最も推奨されます
  2. Angular 9以前: @Component()デコレータに空のテンプレートを指定
  3. サービス機能が必要な場合: @Injectable()デコレータの使用

基底クラスは実体化されないことが想定されるため、abstractキーワードを追加することを忘れないようにしましょう。

詳細については、Angular公式のマイグレーションガイドも参照してください。