0

Is there is any way to get this result in typescript what I have Is there is any way to get property list of parent class directly from class name not from object my end goal is to get this result

export class A {
    public a: string;
    public b: string;
}
export class B extends A {
    public missingProperty: any;
    public constructor(res: any){
      super();
      this.missingProperty = {};
      this.setMissingProperty(res);
    }
    private setMissingProperty(res: any){
       Object.keys(res).foreach(element => {
           // if property name match i.e a is present in res as well as class B then assign to the same 
           // property name 
           // else assign to missingProperty
       }
    }
}

what I want

// test
const temp = {a:'testa', b: 'testb', 0: 23, 1: 34, 2:75}
const b = new B(temp);
// b.b gives testb
// b.a gives testa
// b.missingProperty gives {0: 23, 1: 34, 2:75}
Akash Kumar
  • 182
  • 2
  • 12

1 Answers1

1

TypeScript compiles to JavaScript runtime. Apparently, declaring fields on a class does not initialize it:

console.log(new A()) // prints: { __proto__: {...}}
                     // note how it does not print {a: undefined, b: undefined}
                     // so right now you have no idea what properties A has!
console.log(new B()) // prints: { missingProperty: {}, __proto__: { ... } }
                     // you have no idea what properties A has either!

If you want to know which properties belong to an object at runtime, then your problem is essentially not a TypeScript problem - it is a Javascript problem!

Right now there is no way to know, runtime, if a property is in A. What you could do instead is use A's constructor to initialize these known properties first, so setMissingProperty will know that B already has these A-inherited properties. And then it can loop through and look for the properties that B doesn't have.

class A {
    public a: string;
    public b: string;
    constructor(options) {
      this.a = options.a;
      this.b = options.b;
    }
}
class B extends A {
    public missingProperty: any;
    public constructor(res: any){
      super(res); // B.a, B.b is initialized here
      this.missingProperty = {};
      this.setMissingProperty(res);
    }
    private setMissingProperty(res: any){
      Object.keys(res).forEach(element => {
        if (!Object.prototype.hasOwnProperty.call(this, element)) {
          this.missingProperty[element] = res[element]
        }
      })
    }
}
Jasmonate
  • 752
  • 1
  • 8
  • 18
  • thanks brother but tell me one thing is it important to use .call to explicitly bind scope of this. – Akash Kumar Oct 23 '19 at 05:40
  • I've used `Object.prototype.hasOwnProperty` instead of `this.hasOwnProperty` because any object along B's prototype chain could potentially redefine the `hasOwnProperty` method and break your code. Generally devs do not redefine `Object.prototype.hasOwnProperty`, so calling this function explicitly is safer. Also, if you use `Object.prototype.hasOwnProperty`, binding scope to `this` is necessary, or else `Object.prototype.hasOwnProperty('a')` would try to look for the property 'a' in `Object.prototype`, which is not what you'd want. – Jasmonate Oct 23 '19 at 06:13
  • See https://stackoverflow.com/questions/12017693/why-use-object-prototype-hasownproperty-callmyobj-prop-instead-of-myobj-hasow for more discussion. – Jasmonate Oct 23 '19 at 06:15