Overloading in TypeScript - part 1

April 8, 2013 at 6:12 PMMichele Mottini

Coming from a C#/C++ background I was baffled by the handling of overloading in TypeScript. Having to write a class that could be initialized from either a date or a year/month/day triplet I went for two overloaded constructors:

class DateHour {

  private date: Date;
  private relativeHour: number;

  constructor (year: number, month: number, day: number, relativeHour: number) {
    this.date = new Date(year, month, day);
    this.relativeHour = relativeHour;
  }

  constructor (date: Date, relativeHour: number) {
    this.date = new Date(date.getFullYear(), date.getMonth(), date.getDate());
    this.relativeHour = relativeHour;
  }

}

...that does not work: TypeScript does not accept the two different constructors. The specifications do mention overloading though, so what gives?

The problem is that JavaScript does not know anything about overloading - and so TypeScript cannot generate multiple definitions of the same function differing only by their signature.

What TypeScript can do is to define multiple overloads that all map to the same function body; the class above should be defined like this:

class DateHour {

  private date: Date;
  private relativeHour: number;

  constructor(year: number, month: number, day: number, relativeHour: number);
  constructor(date: Date, relativeHour: number);
  constructor(dateOrYear: any, monthOrRelativeHour: number, day?: number, relativeHour?: number) {
    if (typeof dateOrYear === "number") {
      this.date = new Date(dateOrYear, monthOrRelativeHour, day);
      this.relativeHour = relativeHour;
    } else {
      var date = <Date> dateOrYear;
      this.date = new Date(date.getFullYear(), date.getMonth(), date.getDate());
      this.relativeHour = monthOrRelativeHour;
    }
  }
}

The two overloads are still there, but as simple signature declarations, and the actual implementation of the constructor accepts a superset of the parameters of the two overloads - and determine what to do checking the type of the first parameters.

The clever bit is that in such a case the overloaded signatures hide the implementation one - auto-complete shows only two constructors: 

 and these calls are marked as invalid by the TypeScript compiler:

var start = new DateHour(2013, 0);

var current = new DateHour(new Date(), 1, 4, currentRelativeHour);

even if they match the constructor implementation. The class behaves exactly as if it had the two constructors defined in my first failed attempt.

 Part 2

 

Posted in: Programming

Tags: ,

Add comment

  Country flag

biuquote
  • Comment
  • Preview
Loading