如何在Typescript中组合多个属性装饰器? [英] How to combine multiple property decorators in Typescript?

查看:523
本文介绍了如何在Typescript中组合多个属性装饰器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类 Template ,其属性为 _id ,其中的装饰器来自 class-转换器 typed-graphql

I have a class Template with a property _id which has decorators from class-transformer and 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;
}

现在,我尝试将两者结合成一个新的自定义属性装饰器:

Now I try to combine those two into a new custom property decorator:

/**
 *
 */
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 c $ c> @ExposeToGraphQL()。

The custom decorator works if I only return the result of Expose(), but I don't know how to combine @Expose and @Type in @ExposeToGraphQL().

推荐答案

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

然后您可以按以下方式使用该装饰器:

Then you can use that decorator as follow:

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






您可以找到官方文档在此链接中

@Expose @Type()基本上是装饰工厂。装饰工厂的主要目的是:

@Expose and @Type() are basically Decorator Factories. The main purpose of a decorator factory:


  • 它返回一个函数

  • 该函数将被调用在运行时(在类之后,本例中为 Template ,已定义),带有2个参数:


    • 类原型( Template.prototype

    • 装饰器附加到的属性的名称( _id )。

    • it return a function
    • that function will be called at runtime (right after the class, in this case is Template, was defined) with 2 arguments:
      • class prototype (Template.prototype)
      • name of the property which the decorator attached to (_id).

      如果有两个或多个装饰器附加到相同的属性(称为装饰器组成),评估如下:

      If two or more decorators are attached to a same property (called as Decorator Composition), they are evaluated as follow:


      • 工厂函数的执行顺序与编写代码的顺序相同

      • 工厂功能返回的功能按颠倒的顺序执行

      • The factory functions are executed in the same order as they are written in code
      • The functions returned by factory functions are executed in reversed order

      这篇关于如何在Typescript中组合多个属性装饰器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆