web-dev-qa-db-ja.com

Typescriptで複数のプロパティデコレータを組み合わせる方法は?

__id_と_class-transformer_のデコレータを持つプロパティ_typed-graphql_を持つクラスTemplateがあります

_import {classToPlain, Exclude, Expose, plainToClass, Type } from 'class-transformer';
import { ExposeToGraphQL } from '../../decorators/exposeToGraphQL';
import { Field, ID, MiddlewareInterface, NextFn, ObjectType, ResolverData } from 'type-graphql';
import { getClassForDocument, InstanceType, prop, Typegoose } from 'typegoose';
/**
  * Class
  * @extends Typegoose
  */
@Exclude()
@ObjectType()
class Template extends Typegoose {
  // @Expose and @Type should be both covered by ExposeToGraphQL
  // @Expose()
  @Type(() => String)
  @ExposeToGraphQL()
  @Field(() => ID)
  public _id?: mongoose.Types.ObjectId;
}
_

次に、これら2つを組み合わせて新しいカスタムプロパティデコレータを作成しようとしています。

_/**
 *
 */
import { Expose } from 'class-transformer';
import 'reflect-metadata';

const formatMetadataKey: Symbol = Symbol('ExposeToGraphQL');

function ExposeToGraphQL() {
  console.log('ExposeToGraphQL');

  return Expose();
}

function getExposeToGraphQL(target: any, propertyKey: string) {
  console.log('getExposeToGraphQL');

  return Reflect.getMetadata(formatMetadataKey, target, propertyKey);
}

export {
  ExposeToGraphQL,
  getExposeToGraphQL,
};
_

カスタムデコレータは、Expose()の結果のみを返す場合に機能しますが、@ExposeToGraphQL()で_@Expose_と_@Type_を組み合わせる方法がわかりません。

10
user547995
_import { Expose, Type, TypeOptions, ExposeOptions } from 'class-transformer';

/**
 * Combines @Expose then @Types decorators.
 * @param exposeOptions options that passes to @Expose()
 * @param typeFunction options that passes to @Type()
 */
function ExposeToGraphQL(exposeOptions?: ExposeOptions, typeFunction?: (type?: TypeOptions) => Function) {
  const exposeFn = Expose(exposeOptions);
  const typeFn = Type(typeFunction);

  return function (target: any, key: string) {
    typeFn(target, key);
    exposeFn(target, key);
  }
}
_

次に、そのデコレータを次のように使用できます。

_class Template extends Typegoose {
    @ExposeToGraphQL(/*exposeOptions*/ undefined, /*typeFunction*/ () => String)
    @Field(() => ID)
    public _id?: mongoose.Types.ObjectId;
}
_

デコレータの公式ドキュメントを見つけることができます このリンクで

_@Expose_と@Type()は基本的に デコレータファクトリ です。デコレータファクトリの主な目的:

  • 関数を返します
  • その関数は、実行時に(クラスの直後、この場合はTemplateが定義された後)、2つの引数を使用して呼び出されます:
    • クラスプロトタイプ(_Template.prototype_)
    • デコレータがアタッチしたプロパティの名前(__id_)。

2つ以上のデコレータが同じプロパティにアタッチされている場合( デコレータ構成 と呼ばれます)、それらは次のように評価されます。

  • ファクトリ関数は、コードで記述されているのと同じ順序で実行されます
  • ファクトリ関数によって返される関数は、の順序で実行されます
7
toancaro