Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript property decorator : access to other properties

I have a class Point like this :

class Point {
    @test('admin') x: number = 6

    y: number = 5
}

With Test decorator :

function test(myValue: string) {
    function t(target: Object, propertyKey: string, descriptor: 
    TypedPropertyDescriptor<any>) {
        //want to test y value > x value 
    }
return <any>t
}

In my test I want to check y value for exemple throw an error if x < y

Is it possible ?

like image 415
damien marchand Avatar asked Jan 17 '18 11:01

damien marchand


2 Answers

Your question is similar to this one.

You don't have the context of a specific object instance inside the decorator method. The parameters are the following (from https://www.typescriptlang.org/docs/handbook/decorators.html):

Either the constructor function of the class for a static member, or the prototype of the class for an instance member.

The name of the member.

The Property Descriptor for the member.

like image 96
Lajos Gallay Avatar answered Sep 28 '22 02:09

Lajos Gallay


You can't do it directly from the decorator function. You can, however, use the decorator function to redefine the getter and setter for the property, and access the context object passed into them from there:

class Point {
    @test() x: number;

    y: number;
    
    constructor(x: any, y: any) {
      this.y = y; // Doing this first since the test is on the x setter
      this.x = x;
    }
}

function test() {
  function t(target: Object, propertyKey: string) {
    //want to test y value > x value 
    Object.defineProperty(target, propertyKey, {
      set: function(this, newVal) {
        if (this.y > newVal)
          this._x = newVal;
        else
          throw new Error(`${this.y} is not greater than ${newVal}!`);
      },
      get: function() {
        return this._x;
      }
    });
  };
  return t;
}

try {
  let a = new Point(1, 2);
  console.log(`a = ${a.x}`);
}
catch (ex) {
  console.log(ex);
}

try {
  let b = new Point(3, 2);
  console.log(`b = ${b.x}`);
}
catch (ex) {
  console.log(ex);
}

TypescriptLang Snippet

like image 31
Trevortni Avatar answered Sep 28 '22 03:09

Trevortni