constructor/function overloading

Topics: Language Specification
Jan 21, 2014 at 1:12 AM
Edited Jan 21, 2014 at 1:14 AM
Taylor Mullen & I were mulling about constructor overloads and function overload helpers and came up with the following.
class Rectangle {
    constructor(x: number, y: number, width: number, height: number) => (new eg.Vector2d(x, y), new eg.Size2d(width, height));
    constructor(position: eg.Vector2d, size: eg.Vector2d) {
        /* notice we don't supply a final constructor */
        this.Position = position;
            this.Size = size;
    }
}
Behind the scenes when compiling to javascript it could generate the following
var Rectangle = (function () {
    function Rectangle(arg1, arg2, arg3, arg4) {
        if(arg1 && arg2 && arg3 && arg4 && 
           typeof arg1 === "number" && typeof arg2 === "number" &&
           typeof arg3 === "number" && typeof arg4 === "number") {
            arg1 = new eg.Vector2d(arg1, arg2); /* this code comes from the declaration mapping itself with remapped arguments */
            arg2 = new eg.Size2d(arg3, arg4);
        }
        this.Position = arg1;
        this.Size = arg2;
    }
    return Rectangle;
})();
The idea is you define a mapping from one constructor to another and the compiler generates the code involved to translate from constructor a to constructor b. The main portion of the generated code would be for parameter type checking. The rest of the code is actually supplied by the conversion.

This is obviously a very specific example and there are already issues I can see with it as it wouldn't support type checking against interfaces so two constructors with the same number of params only differing by interface type.

However this does solve a major issue with constructor overloading.
Coordinator
Jan 21, 2014 at 5:59 PM
We've looked into having separate functions for overloads, but unfortunately it doesn't work in all cases. For example, I'm not sure what the compiler would produce in an example that overloaded on function type:

class Rectangle {
    constructor(x: (y: number)=>number) { ... }
    constructor(x: (y: string)=>string) { ... }
}
Here, I believe all we see for typeof is that they are both typeof "function".
Jan 21, 2014 at 6:38 PM
That looks to be running different code depending on constructor. My goal was to use the existing constructor declarations that we're forced to use anyway but allow a simpler way of mapping parameters from one constructor to another. so...
class Rectangle {
    constructor(x: (y: number) => number);
    constructor(x: (y: string) => string);
    constructor(g: any) {
         //you can't tell what g is here anyway
    }
}
In this example mapping wouldn't do anything anyway since you have to handle it as if it was typeless but the examples I gave allow you to just massage the incoming data rather than run different code based on incoming data. You're still constrained to the limitations of js.

In this type of example if you were to provide => mapping on the first constructor to the second one the compiler could give a warning saying that the signature types couldn't be determined or something.