Ole
Ole

Reputation: 46900

Typescript Decorator gets called twice

I created an issue report with Typescript because I'm pretty sure this is a bug, but I wanted to check here as well just in case anyone had additional insight.

This is what is happening. When the following code is run:

class Person {
    @IsValueIn(['PETER', 'JAMES'])
    @IsAlpha()
    @IsDefined()
    public name:string;
}

It will log this:

Error in /turbo_modules/@fireflysemantics/[email protected]/bundles/fireflysemantics-validator.umd.js (194:21)
The ValidationContainer
already contains context with signature IsValueIn_Person_name.

But if we comment out @IsValueIn(['PETER', 'JAMES']):

class Person {
    //@IsValueIn(['PETER', 'JAMES'])
    @IsAlpha()
    @IsDefined()
    public name:string;
}

There are no exceptions.

When the runtime sees and instantiates a decorator, the following function is called (I've added logging statements that show that the decorator is called twice):

  /**
   * @param target Add a ValidationContext instance.
   * @throws Error if attempting to add a ValidationContext with a signature that duplicates that of an instance already contained.
   * 
   * If an exception thrown it indicates that a duplicate class definition exist
   * in the runtime.  In other words the same class definition is loaded more
   * than once because it exists in multiple files.
   * 
   */
  public static addValidationContext(target: ValidationContext): void {

    const key: string = getPropertyKey(
      target.target.name,
      target.propertyName
    );

    console.log("The property key is: ", key)
    console.log("The target signature is: ", target.getSignature())

These are the logging statements executed:

ValidationContainer.ts:69 The target signature is:  IsDefined_Person_name
ValidationContainer.ts:68 The property key is:  Person_name
ValidationContainer.ts:69 The target signature is:  IsAlpha_Person_name
ValidationContainer.ts:68 The property key is:  Person_name
ValidationContainer.ts:69 The target signature is:  IsValueIn_Person_name
ValidationContainer.ts:68 The property key is:  Person_name
ValidationContainer.ts:69 The target signature is:  IsValueIn_Person_name

As can be seen the IsValueIn_Person_name is created twice, as a result of the decorator instantiation happening twice, and this produces the exception.

Thoughts?

Upvotes: 0

Views: 740

Answers (1)

Estradiaz
Estradiaz

Reputation: 3563

The assumption that the decorator is called twice based on logs is wrong.

In current source:

export function IsValueIn(target: any[], validationOptions?: ValidationOptions) {

  const validationParameters:any[] = [];
  validationParameters.push(target);

  return function(object: any, propertyName: string) {
    const vc: ValidationContext = new ValidationContext(
      object,
      object.constructor,
      IsValueIn.name,
      propertyName,
      validateValue,
      null,
      true,
      errorMessage,
      validationOptions
    );
    ValidationContainer.addValidationContext(vc);
    ValidationContainer.addValidationContext(vc);
  };
}

ValidationContainer.addValidationContext(vc); is called twice and produces those double logs.

Just get rid of line 33 or 34 ;)

Upvotes: 2

Related Questions