如何在Typescript中组合多个属性装饰器? [英] How to combine multiple property decorators in 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屋!
- class prototype (
- 类原型(