Programmingフルスタック開発者

TypeScriptにおけるデコレータ(Decorator)はどのように機能しますか?それらは何のために使用され、カスタムデコレータをどのように実装し、作業中にどのような落とし穴がありますか?

Hintsage AIアシスタントで面接を突破

回答。

デコレータは、クラス、プロパティ、メソッド、またはパラメータの動作を変更する特別なアノテーションであり、追加のメタ情報または実装の置き換えを通じて行います。

通常、依存性の注入、ロギング、バリデーション、キャッシング、またはAngularのようなフレームワーク用のメタデータの宣言に使用されます。

メソッドのシンプルなデコレータの例:

function Log(target: any, propertyKey: string, descriptor: PropertyDescriptor) { const original = descriptor.value; descriptor.value = function(...args: any[]) { console.log(`Call: ${propertyKey}(${JSON.stringify(args)})`); return original.apply(this, args); }; } class Example { @Log doSomething(a: number, b: number) { return a + b; } }

落とし穴:

  • デコレータは、tsconfigでexperimentalDecoratorsを有効にしなければ機能しません。
  • 一部のstrict modeの設定と互換性がありません。
  • デコレータは期待される順序で呼び出されるとは限らないため、呼び出しスタックを理解することが重要です。
  • パラメータのデコレータは、その値を直接変更することを許可しません。

引っかけ問題。

質問: "デコレータに適用されるメソッドの型を保証するようにパラメータを型付けすることはできますか?"

回答: ほとんどの場合、デコレータの適用時に型付けは不可能です。メタプログラミングの動的な性質のためです。ただし、ジェネリクスや追加のランタイムチェックを通じてバリデーションを追加できますが、TypeScriptのコンパイラは構造の宣言段階で保証を与えません。

例:

function MyDecorator(target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<number>) { /* ... */ } // コンパイラはメソッドがnumberを返すことを保証しません

テーマの細部の不明による実際のエラーの例。


物語

デコレータが多数あるサービスのプロジェクトで、適用順序を忘れたため、プロパティデコレータがすべてのパラメータの前に適用され、Injectメタデータを失い、実行時に依存関係を解決できなくなりました。


物語

開発者がクラスのメソッドではなく通常の関数にデコレータを適用しようとし、コンパイルエラーや実行時効果の欠如に驚きました。TypeScriptの仕様では、デコレータはクラスとそのメンバーにのみ適用されます。


物語

TypeScriptのバージョンを更新し、実験的設定を行った後、カスタムDIコンテナのデコレータ機構が壊れました。新しいバージョンはReflect-metadataの明示的なサポートを要求し、それがないとすべてのメタ情報が失われることがわかりました。