TypeScript Academy · レッスン

reflect-metadataとDesign Types

実行時にパラメーターとプロパティの型を取得します。

レッスン 3/413 ステップ

「reflect-metadataとDesign Types」はCoddyKit上の無料TypeScript Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはTypeScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 TypeScript Academyコースには全4レッスンが含まれています。

reflect-metadata と設計時型

標準化されたメタデータが存在する前は、TypeScript は reflect-metadata ライブラリと emitDecoratorMetadata コンパイラフラグを使って、設計時の型情報をランタイムに出力できました。このレッスンでは、古いものの現在も広く使われているこの仕組みを扱います。

機能を有効にする

必要なことは2つあります。コンパイラーオプションを有効にし、プログラムのエントリーポイントでライブラリを一度インポートします。

// tsconfig.json
// {
//   "compilerOptions": {
//     "experimentalDecorators": true,
//     "emitDecoratorMetadata": true
//   }
// }

import "reflect-metadata";

出力されるもの

emitDecoratorMetadata を有効にすると、コンパイラーはデコレーターが付いたメンバーに対して、design:type、design:paramtypes、design:returntype の3つのキーを出力します。値はコンストラクター関数です(例: String、Number)。

design:type の読み取り

デコレーターが付いたプロパティでは、Reflect.getMetadata("design:type", target, key) がプロパティの型のコンストラクターを返します。

import "reflect-metadata";

function track(target: any, key: string) {
  const t = Reflect.getMetadata("design:type", target, key);
  console.log(key, "->", t.name); // e.g. "name -> String"
}

class Person {
  @track name!: string;
  @track age!: number;
}

design:paramtypes の読み取り

コンストラクターまたはメソッドでは、design:paramtypes はパラメーターの型コンストラクターの配列です。これは依存性注入の基盤になります。

function injectable(target: any) {
  const params = Reflect.getMetadata("design:paramtypes", target);
  console.log(params.map((p: any) => p.name)); // ["Database", "Logger"]
}

@injectable
class Service {
  constructor(private db: Database, private log: Logger) {}
}

出力される型の制限

ランタイムで表現できる単純な型だけが残ります。インターフェース、ユニオン、ジェネリクスにはランタイムのコンストラクターがないため、Object に変換されます。設計時型は近似値であり、完全な TS の型ではありません。

Reflect によるカスタムメタデータ

設計時型とは無関係に、Reflect.defineMetadata を使って独自のメタデータキーを定義することもできます。

import "reflect-metadata";

function required(target: any, key: string) {
  Reflect.defineMetadata("required", true, target, key);
}

function isRequired(target: any, key: string) {
  return Reflect.getMetadata("required", target, key) === true;
}

利用されている場所

この仕組みは、多くの確立されたフレームワーク(NestJS、TypeORM、class-validator)を支えています。これらは design:type と design:paramtypes を読み取り、型を再度記述しなくても依存関係の接続や値の検証を行います。

reflect-metadata と標準メタデータの比較

新しい Symbol.metadata API は言語の一部であり、設計時型を出力しません。reflect-metadata は型情報を提供できる独自の仕組みですが、実験的なデコレーターモードに依存しています。プロジェクトごとにどちらか一方のモデルを選択してください。

インポート順序が重要な理由

import "reflect-metadata" は、デコレーターが付いたクラスが評価される前に一度だけ実行する必要があります。これは、メタデータ関数を使えるようにグローバルな Reflect オブジェクトを拡張するためです。エントリーファイルの最上部でインポートしてください。

重要な理由

設計時型を出力すると、フレームワークはコンパイル時の型とランタイムの動作の間を橋渡しできます。これは、使いやすい DI とバリデーションを実現する重要な要素です。インターフェースやジェネリクスには対応しないという制限を知っておけば、予期しない Object の結果を防げます。

理解度チェック

reflect-metadata の理解度を確認しましょう。

まとめ

experimentalDecorators と emitDecoratorMetadata を有効にし、早い段階で import "reflect-metadata" を実行すると、コンパイラーは design:type と design:paramtypes をランタイムのコンストラクターとして出力します。フレームワークはこれらを DI やバリデーションに利用しますが、インターフェース、ユニオン、ジェネリクスは Object に変換されます。

無料で開始

AI チューターと学ぶ TypeScript — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
101
レッスン
352

よくある質問

「reflect-metadataとDesign Types」レッスンは無料ですか?

はい。「reflect-metadataとDesign Types」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、TypeScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 TypeScript Academyコースには全4レッスンが含まれています。

「reflect-metadataとDesign Types」で何を学びますか?

実行時にパラメーターとプロパティの型を取得します。 ブラウザで直接実行するハンズオンコードでTypeScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

TypeScript Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのTypeScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「reflect-metadataとDesign Types」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このTypeScript Academyレッスンでコードを書いて実行できますか?

はい。すべてのTypeScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Stage 3デコレーターの解説
  2. デコレーターのメタデータ
  3. reflect-metadataとDesign Types
  4. デコレーターフレームワークの構築
← TypeScript Academyに戻る