David Elsner David Elsner - 2 months ago 41
TypeScript Question

TypeScript constructor in interface

The typescript doc says something about the following code:

interface ClockConstructor {
new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
tick();
}

function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
return new ctor(hour, minute);
}

class DigitalClock implements ClockInterface {
constructor(h: number, m: number) { }
tick() {
console.log("beep beep");
}
}
class AnalogClock implements ClockInterface {
constructor(h: number, m: number) { }
tick() {
console.log("tick tock");
}
}

let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);


...


Because createClock’s first parameter is of type ClockConstructor, in
createClock(AnalogClock, 7, 32), it checks that AnalogClock has the
correct constructor signature.


However, compiling the same code without the constructor, does not throw an error like you can see here

Why is that? Am I missing anything?

Answer

Not having a constructor in the ts class will still create one in the compiled js:

class DigitalClock implements ClockInterface {
    tick() {
        console.log("beep beep");
    }
}

Compiles into:

var DigitalClock = (function () {
    function DigitalClock() {
    }
    DigitalClock.prototype.tick = function () {
        console.log("beep beep");
    };
    return DigitalClock;
}());

So there's a constructor there which doesn't receive any arguments, but in javascript you can still call a function that doesn't declare any arguments with arguments:

function fn() {
    console.log(arguments);
}
fn(1, 2, 3); // [1, 2, 3]

In this case however typescript will complain about calling fn with arguments.
But this will be ok:

type MyFunction = { (a: number, b: number, c: number): void }

(fn as MyFunction)(1, 2, 3);

I guess that the compiler just trusts you that you know what you are doing, as the ctor exists and you can in fact get those arguments from the arguments object.

This how ever will fail:

class AnalogClock implements ClockInterface {
    constructor(str: string) {}
    tick() {
        console.log("tick tock");
    }
}
let analog = createClock(AnalogClock, 7, 32);

Because now there's a different ctor signature.