JSFiddle - React, Tailwind, and code Playground

JavaScript

function addProperty(
    instance,
    label,
    getter,
    setter,
    enumerable = true
  ) {
    Object.defineProperty(instance, label, {
      get: getter,
      set: setter,
      enumerable: enumerable,
    });
    return instance;
  }

function copy(obj, sub = Object.create({})) {
    const props = Object.getOwnPropertyNames(obj);
    // grab instance variables and function
    props.forEach((prop) => {
      const methodDef = Object.getOwnPropertyDescriptor(obj, prop);
      // check if this property uses accessor methods (Object.assign can't do this!)
      if (methodDef && (methodDef.get || methodDef.set) && !sub[prop]) {
        // yep
        addProperty(
          sub,
          prop,
          Object.getOwnPropertyDescriptor(obj, prop).get,
          Object.getOwnPropertyDescriptor(obj, prop).set
        );
      } else if(!sub[prop]) {
        // nope
        sub[prop] = obj[prop];
      }
    });
    if (obj.__proto__) {
      this.copy(obj.__proto__, sub);
    }
    return sub;
  }
  
  class vo1 {
    constructor(a = 'a'){
      this._a = a;
    }
    
    log() {
      console.log('hellow world, I am and isntance of vo2');
    }
    
    get a() {
       return this._a;
    }
    
  }
  
  class vo2 extends vo1 {
    constructor(a = 'a', b = 'b'){
      super(a);
      this._b = b;
      this._a = a;
    }
    
    log() {
      console.log(`hellow world, I am and isntance of vo2 and my values are a: ${this.a} b: ${this.b}`);
    }
    
    get b() {
       return this._b;
    }
    
  }
  const clone = copy(new vo2('x', 'z'));
  console.log(clone);
  console.log(clone.log());
  // note all accesors are methods are defined, yeah!
  const methodDef = Object.getOwnPropertyDescriptor(clone, 'b');
  console.log(methodDef);
  // lets try that with spread
  const clone2 = {...new vo1(), ...new vo2('x', 'z')};
  console.log(clone2);
  // error, log is not defined, and neither are our accessor methods
  console.log(clone2.log());