web-dev-qa-db-ja.com

すべてのプロパティ名を定義したインターフェイスを取得するための「コンパイル時」の方法

特定のinterfaceを実装するオブジェクトの配列を(HTMLリストとして)レンダリングするための汎用TypeScriptクラスを作成したいと思います。

例えば.

class GenericListRenderer<T> {
  items: T[];

 constructor(listItems: T[], className?: string){
      this.items = listItems;
      ...
    }

    private getPropertyNames(): string[]{

    // What is the best way to access all property names defined in
    // TypeScript interface 'T' that was used in this generic?
    ...   
    }

    render(){
      var propNames: string[] = this.getPropertyNames();
      // render list with each item containing set of all 
      // key(prop name)/value pairs defined by interface 'T'  
      ...

    }
}

Q:指定された()TypeScriptインターフェイスで定義されているすべてのプロパティ名の「コンパイル時」リストを取得するための最良の方法は何ですか?

C++テンプレートと同様に、TypeScriptは、(コンパイル時に)TypeScriptタイプ情報(特定のオブジェクトをインスタンス化するために使用されるジェネリックに提供されるインターフェイスなど)がすぐに利用できるときにこれらのジェネリックを解決できると考えています。

必要なすべての型情報が提供される可能性があるため、「バニラ」Javascriptオブジェクトの過度のランタイムフィルタリングなしでこの情報にアクセスできるTypeScript拡張機能が存在するかどうか不思議でした-あいまいな継承の問題が原因で問題になる可能性があります(たとえば、ランタイム、ジェネリック、Javascript(obj.hasOwnProperty(prop))がプロパティのフィルタリングに使用されている場合、必要なTypeScript継承インターフェイスプロパティが除外されることがあります)。

この便利なプロパティイントロスペクションの可能性は、「コンパイル時」にTypeScriptのタイプメタデータのスーパーセットを使用することで、このタイプの情報がすべて破棄された場合に、翻訳されたJavaScriptでこの情報を解決しようとすることで、明確に解決できます。

標準(TypeScript)アプローチが存在する場合、不完全な可能性のあるJavascriptハックで「車輪を再発明」するのは嫌です。

25
user3413621

これは、TypeScript> = 2.4.1で利用可能な https://github.com/Microsoft/TypeScript/pull/1394 で導入されたカスタムトランスフォーマーを使用することで可能になります。

私のnpmパッケージ ts-transformer-keys は良い例です。

import { keys } from 'ts-transformer-keys';

interface Props {
  id: string;
  name: string;
  age: number;
}
const keysOfProps = keys<Props>();

console.log(keysOfProps); // ['id', 'name', 'age']
19
kimamula

これは、実行時にその情報を取得することはできません。また、コンパイル中に保存しない限り、デフォルトでそれらを使用することはできません。したがって、解決策は ReflectDecorators を使用して反映されます。

ここ は、実行時にコンパイル時のメタデータを取得する問題をカバーする優れた記事です。つまり、説明を保持したいインターフェイスにデコレータを追加します。これは、コード自体に格納されるJSONオブジェクトに変換されます。実行時に、すべてのインターフェースデータを持つこのJSONオブジェクトを取得できます。これは現在実験段階(2016年2月11日)ですが、良い方法です。

注:デフォルトでは決して実行されない理由は、基本的に、TSがjsコードにメタデータをオーバーロードしないように設計することです(Dartとは異なります)。

6
Flavien Volken

あなたが呼び出すことによってあなたが必要とするすべての情報を得ることができます

let test = Object.keys(instanceOfObject)

これを記録すると console.log(テスト)、あなたは次のようなものを得ます:

0: "user_id"
...
26: "address"
length: 27

test.lengthなど、このオブジェクトに関するすべての情報にアクセスできます。

From: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

0
Sethrone