/**
 * @interface
 */
class Base {
  constructor() {
    Object.assign(this, this.constructor.castConstructorData(...arguments));
  }
  clone() {
    return new this.constructor(this);
  }
  static castConstructorData() {};
}
class Point extends Base {
  /**
   *
   * @param {(number|Point|{x: number, y: number})} pointOrX
   * @param {number} [y]
   */
  constructor(pointOrX, y) {
    super(...arguments);
  }
  /**
   * @see Point
   */
  static castConstructorData(pointOrX, y) {
    if (typeof pointOrX === 'number') {
      return {x: pointOrX, y};
    }
    if (typeof pointOrX === 'object') {
      return {x: pointOrX.x, y: pointOrX.y};
    }
    throw new TypeError(`Invalid arguments for Point`);
  }
}
console.log(new Point(1, 2));
console.log(new Point({x: 1, y: 2}));
console.log(new Point(new Point(1, 2)));
console.log(new Point(1, 2).clone());