Typescript - inline class without dynamically added properties

I have a set of typescript objects that have been triggered, but in code I need to dynamically add some properties to this object. If I need to serialize an object by specifying it - how can I do that so that it doesn't include dynamically added properties? Since I have many classes and inner classes, I am looking for a general approach rather than one by one.

So, as an example, I have a class defined like this:

 export class Car {

  public colour: string = '';
  public model: string = '';
  public diesel?: boolean = false;

  constructor () {}
}

      

Now in code, I am setting the above car as the one I am currently driving:

let car: Car = new Car();
car.model = 'modelA';
car.colour = 'black';

car['active'] = true;

      

And then somewhere in the code I need to take the active car and serialize the object so that I can send the data to the server:

JSON.stringify({'data': car});

      

What I'm looking for is now a string representation of an object with no dynamically added properties, but the approach is generic so I don't need to describe what I want to remove.

All help is needed; -)

+3


source to share


3 answers


You can keep a list of "known keys" and use them in serialization:

class Car {
    private static keys = ["colour", "model", "diesel"];

    public colour: string = '';
    public model: string = '';
    public diesel?: boolean = false;

    constructor() { }

    toJsonString(): string {
        const data = {};
        Car.keys.forEach(key => data[key] = this[key]);

        return JSON.stringify(data);
    }
}

      

You can use decorators to create this static list.



Or:

class Car {
    public colour: string = '';
    public model: string = '';
    public diesel?: boolean = false;

    constructor() {
        this.toJsonString = function (keys) {
            const data = {};
            keys.forEach(key => data[key] = this[key]);

            return JSON.stringify(data);
        }.bind(this, Object.keys(this));
    }

    toJsonString: () => string;
}

      

+1


source


You can create a car and it will only have normal properties. Then flip all its properties and copy the value from another car:

let car: Car = new Car();
car.model = 'modelA';
car.colour = 'black';

car['active'] = true;

let withoutDynamics = new Car();

for (let prop in withoutDynamics) {
    // Check for hasOwnProperty if you like, depending on whether you
    // properties from the prototype
    withoutDynamics[prop] = car[prop];
}

JSON.stringify({'data': withoutDynamics });

      



You can include this in a generic function to be used with other classes (if they have a constructor that takes no parameters):

function noDynamics<T>(type: { new (): T; }, withDynamics: T): T {
    let withoutDynamics = new type();

    for (let prop in withoutDynamics) {
        withoutDynamics[prop] = withDynamics[prop];
    }

    return withoutDynamics;
}

JSON.stringify({'data': noDynamics(Car, car) });

      

0


source


You can store an array of original keys in a property and use a custom toJSON

implementation in your class to control that only the original keys are serialized:

export class Car {

    public colour: string = '';
    public model: string = '';
    public diesel?: boolean = false;
    private _keys: string[] // Note that this is not initialized

    constructor() {
        this._keys = Object.keys(this);
    }

    toJSON() {
        var obj: any = {};
        this._keys.forEach(key => {
            obj[key] = this[key]
        });
        return obj
    }
}

let car: Car = new Car();
car.model = 'modelA';
car.colour = 'black';
car['active'] = true;

console.log(JSON.stringify({ 'data': car }));

      

0


source







All Articles