i want to extend from one class but delete some property

Viewed 3826

I have some class for crud API service class I want to extend it but spear few properties for exam this is my class

class Parent {
  public propertyToKeep: any;
  public propertyToDelete: any;
  constructor() { }
}

this is the child class

class Child extends Parent {
  constructor() {
    super();
  }
}

Another file where I don't want to see and get access to

export class comeComponent {
  constructor(private child: Child) {
    this.child.propertyToKeep // work
    this.child.propertyToDelete // error and I can't even see it
  }
}
4 Answers

Just came accross the same use case as you and here's how I dit it :

const Omit = <T, K extends keyof T>(Class: new () => T, keys: K[]): new () => Omit<T, typeof keys[number]> =>
  Class;

then you can use it like so :

class Child extends Omit(Parent, ['propertyToDelete']), {}

as you can see chlid only has one property now (it also works with methods).

The package from @nestjs/swagger has some nice helpers if you're dealing with a NestJS API. Their implementation is more complexe so I guess they're keeping other stuff like their own property decorators (I'm pretty new to Typescript so maybe I miss the point of all they're doing).

P.S: First answer + French guy so not a perfect English, please be kind ^^

Here's one way to do it:

class Parent {
  propertyToKeep = 'hi';
  propertyToDelete = 'bye';
  constructor() {}
}

class Child extends Parent {
  constructor() {
    super();
    delete this.propertyToDelete;
  }
}

const myObject = new Child();

console.log(myObject);
//{
//  "propertyToKeep": "hi"
//}

You need to use Object.defineProperty function, for make a restriction in descriptor, enumerable to false and getter, setter with specific condition, here a complete example:

//A small example of how to make an invisible property in Child class.

class Parent{
 
 constructor(){
 
  this.propertyToKeep = "Visible";
  this.propertyToDelete = "Not visible in subclass child";
 
 }
}

Object.defineProperty(Parent.prototype, "propertyToDelete",  {enumerable: false,
 configurable: true,
 get: function(){
     if(!(this instanceof Child)){

        return this._propertyToDelete;
     }
 },
 set: function(v){
    
    if(!(this instanceof Child)){

        this._propertyToDelete = v;
    }
    

 }});

 Object.freeze(Parent.prototype);

class Child extends Parent {
  constructor() {
    super();
  }
}

//console.log(Child.prototype);

let chd = new Child();

console.log("Child: --------------------------------");

console.log(chd);

console.log(chd.propertyToDelete); //Undefined

console.log("Parent: -------------------------------");

let prt = new Parent();

console.log(prt);

console.log(prt.propertyToDelete); //"Not visible in subclass child"

/*let chdObj = Object.getOwnPropertyDescriptors(Child.prototype);

console.log(chdObj);*/


class SomeComponent{

  #child;

  constructor(child) {
    
    this.#child = child;

    

    console.log(this.#child); //{propertyToKeep: "Visible"}

    console.log(this.#child.propertyToKeep /*work*/);
    
    console.log(this.#child.propertyToDelete /*undefined*/);


  }
}


//Now i will invoke SomeComponent

console.log("SomeComponent: -------------------------");

let sc = new SomeComponent(new Child());

That's not possible. If you declare an attribute in a parent class, you can't restrict his visibility in a child class.

From the model design point of view, that doesn't make sense as well. The problem you are exposing here indicates that your class hierarchy is not well designed and you must rethink and redesign it.

Related