Inheritance: declare a method that returns the current instance class
let v = new Vector2(1, 2);
let w = v.opposite();
// this is wrong, since w is not a 2-dimensional vector
console.log(w.x);



The fact that the .opposite() returns a result that does not fit into the expected use cases, suggests that there is a design issue. In other words, it is a "hint" that Vector2 is not really a Vector in terms of OOP. Why so? Because it does not follow the intuitive contract in which the .opposite() method returns same exact type of the vector as the one on which the method is being invoked. Things will only get worse if one will need to work against a Vector3, Vector4, etc.

There's whole bunch of sources that explain how inheritance is very often not the best way to create new types nor reuse code.

If I was to design the VectorOf2, I would make it wrap the Vector class rather than inherit from it.

class VectorOf2 {
    private _vector: Vector;

    constructor(x: number, y: number) {
        this._vector = new Vector(x, y);
    }

    get x(): number {
        return this._vector[0];
    }

    get y(): number {
        return this._vector[1];
    }

    opposite(): VectorOf2 {
        return new VectorOf2( ... );
    }
}


With this design, each method added to Vector2 is always Vector2-specific and there's no confusion about it. The regular Vector's method can still be reused by VectorOf2 when a new method is implemented.