Как объединить несколько декораторов свойств в Typescript?

У меня есть класс Template с собственностью _id который имеет декораторы из class-transformer а также typed-graphql

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;
}

Теперь я пытаюсь объединить эти два в новый пользовательский декоратор свойств:

/**
 *
 */
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(), но я не знаю, как совместить @Expose а также @Type в @ExposeToGraphQL(),

1 ответ

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).

Если два или более декоратора присоединены к одному и тому же свойству (называемому " Компоновка декоратора"), они оцениваются следующим образом:

  • Заводские функции выполняются в том же порядке, в каком они написаны в коде.
  • Функции, возвращаемые фабричными функциями, выполняются в обратном порядке.
Другие вопросы по тегам