admin管理员组

文章数量:1331621

Is there a way to solve massive decorator use inside classes?

Here's an example of a single property of a class in my NestJS app, with an inplete swagger documentation decorator:

  @ApiModelProperty({
    description: 'description',
  })
  @Expose()
  @MaxLength(100, { message: 'message' })
  @IsString({ message: 'message' })
  @ValidateIf(address=> address.id !== null)
  @NotEquals(undefined, { message: 'message' })
  address: string;

This gets huge and ugly in no time. Any way to make the code look cleaner, defining the decorators in another file, maybe?

Is there a way to solve massive decorator use inside classes?

Here's an example of a single property of a class in my NestJS app, with an inplete swagger documentation decorator:

  @ApiModelProperty({
    description: 'description',
  })
  @Expose()
  @MaxLength(100, { message: 'message' })
  @IsString({ message: 'message' })
  @ValidateIf(address=> address.id !== null)
  @NotEquals(undefined, { message: 'message' })
  address: string;

This gets huge and ugly in no time. Any way to make the code look cleaner, defining the decorators in another file, maybe?

Share Improve this question edited Oct 1, 2019 at 20:33 Julián asked Oct 1, 2019 at 20:00 JuliánJulián 3383 silver badges16 bronze badges 4
  • Could you define what you mean by solve? – Olian04 Commented Oct 1, 2019 at 20:11
  • 1 If a library decides to use decorators it uses decorators ... not really much can be done about it .. maybe define some pound decorators.. – Titian Cernicova-Dragomir Commented Oct 1, 2019 at 20:16
  • @Olian04 By solve i mean not having so much lines of decorations in one single file, they make code hard to read and you have different types of them mixed (i.e. validation and documentation). Example, using express-validator you sometimes got a huge chained validation, but thanks to how the router uses middleware, you could remove that from your file into another one, then importing it as an array of validation middlewares. That makes code super clean.But I have little experience using decorators and i wanted to know if there is a way to have similar results. – Julián Commented Oct 1, 2019 at 20:24
  • A couple of things to take a look into, see if you can cut down on the number of decorators you are using. You have a @ValidateIf(address => address.id !== null) but your address type is string which doesn't have an id field. @Expose() is only needed if you want to expose the field of the class, but have no real validations to run against it, so there's an extraneous decorator. I'm pretty sure you can get rid of the @NotEquals() possibly by options in the @IsString() decorator or by using the @Length() decorator to bine your max and min length (1,100). – Jay McDoniel Commented Oct 1, 2019 at 21:57
Add a ment  | 

3 Answers 3

Reset to default 9

Decorators are regular typescript functions. You can try to pose multiple decorators into a single one. For exemple, you could mix the validation ones into a single decorator, like this:

function apiStringField(maxLength: number, message: string, description?: string) {
  return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) { 
      ApiModelProperty()(target, propertyKey, descriptor)
      Expose()(target, propertyKey, descriptor)
      MaxLength(maxLength, { message })(target, propertyKey, descriptor) 
      IsString({ message })(target, propertyKey, descriptor)
      NotEquals(undefined, { message })(target, propertyKey, descriptor) 
  }
}

And, use it like this (after importing it):

@apiStringField(100, 'message', 'description')
address: string;

Not really sure for how long this has existed under nestjs/mon library, but I stumbled with this issue and in case someone else stumbles with this. After requesting help on their official discord, jmcdo29 suggested https://docs.nestjs./custom-decorators#decorator-position which seems like the way to go.

This good nestjs util helped in my case, maybe it helps you:

import { applyDecorators } from '@nestjs/mon';

expose function ComposedDecorator(options: any) {
  return applyDecorators(
    Decorator1(),
    Decorator2(),
    AnotherDecoratorYouWant(),
  )
}

And then:

@ComposedDecorator(options)
// methodOrClassOrProperty

本文标签: javascriptTypescript decorator messStack Overflow