TypeScript Classes and Interfaces – Part 3 | John Papa

John Papa

Evangelist on the loose

TypeScript Classes and Interfaces – Part 3

...

It’s likely that you’ve used classes and interfaces in statically typed languages to organizing your code into logical units. When you work with JavaScript these constructs do not exist, so we use the excellent replacements like constructor functions and the module pattern. However, you may still miss classes and interfaces (which play together quite nicely) and if so, you may want to take a closer look at TypeScript. Classes are being discussed for the next ECMAScript 6 revision, and as such, TypeScript has taken them under its wing.
typescript classes

Dan Wahlin and I just released a new course for Pluralsight that focuses on providing the fundamentals to write application-scale code using TypeScript.
tslogo

This post should give you a primer on what’s in the 3rd module of our course (where we cover classes and interfaces in depth). This is part 3 of 4 in an article series where I describe the different areas Dan and I feel are fundamental to learning TypeScript. You can find the other posts here:

Do I Need Classes?

I generally consider 3 main conditions where I consider a class, regardless of the language.

  • Creating multiple new instances
  • Using inheritance
  • Singleton objects

There are others, but let’s look at these 3. For singletons I could just as easily use the Module Pattern, and frankly I generally do that with TypeScript. For creating instances, classes are nice but they are not necessary in JavaScript either.

Let me be clear that classes are pretty awesome, but it’s not like we can’t do these things in JavaScript today using other techniques. The reason TypeScript’s classes are valuable is not because you can’t do them today, it’s because they make it so much easier to do these things. If you want an example, try to write your own class structure that uses inheritance in JavaScript.

If you take anything out of this post, take this: TypeScript makes it easier to write structured code, and part of that is using classes.

Creating a Class

You can create a class and even add fields, properties, constructors, and functions (static, prototype, instance based). The basic syntax for a class is as follows:

// TypeScript
class Car {
    // Property (public by default)
    engine: string;

    // Constructor 
    // (accepts a value so you can initialize engine)
    constructor(engine: string) {
        this.engine = engine;
    }
}  

This code creates a Car class that has a constructor that accepts a single parameter engine that initializes the instance property with the same name. so we can write

var hondaAccord = new Car('V6');

The engine property is defined as being public (public is the default). We could have simply put the public keyword there too. The property could be made private by prefixing the definition with the keyword private. Inside the constructor the engine property is referred to using the this keyword. This code emits this JavaScript:

// JavaScript
var Car = (function () {
    function Car(engine) {
        this.engine = engine;
    }
    return Car;
})();

Functions

You can create a function on an instance member of the class, on the prototype, or as a static function. Often you will want to use the prototype for the functions on classes if you intend to create multiple instances of the object. Why? Because the prototype can save you some memory as it only exists once while creating a function on every instance of the class would create 1 function per instance. Creating a function on the prototype is easy in TypeScript, which is great since you don;t even have to know you are using the prototype.

// TypeScript
class Car {
    engine: string;
    constructor (engine: string) {
        this.engine = engine;
    }

    start() {
        return "Started " + this.engine;
    }
} 

Notice the start function in the TypeScript code. Now look at the emitted JavaScript below, which defines that start function on the prototype.

// JavaScript
var Car = (function () {
    function Car(engine) {
        this.engine = engine;
    }
    Car.prototype.start = function () {
        return "Started " + this.engine;
    };
    return Car;
})();

But if you want to create a function as an instance member, you can do so like this:

// TypeScript
class Car {
    engine: string;
         stop: () => string;
    constructor (engine: string) {
        this.engine = engine;
        this.stop = () => "Stopped " + this.engine;
    }

    start() {
        return "Started " + this.engine;
    }
}

One way to create a function like this is to do it in the constructor. The emitted JavaScript now shows that the start function is on the prototype and the stop is an instance function. It’s not a great design to mix these, your better off picking one or the other.

// JavaScript
var Car = (function () {
    function Car(engine) {
        var _this = <span class="hiddenGrammarError" pre="var ">this;
        this</span>.engine = engine;
        this.stop = function () {
            return "Stopped " + _this.engine;
        };
    }
    Car.prototype.start = function () {
        return "Started " + this.engine;
    };
    return Car;
})();

Inheritance

Class inheritance, as you are probably familiar with it, is not is not something you’d want to hand code in JavaScript. This is an area that TypeScript clearly shines brightly. For example, you can define an Auto class and then define a ManlyTruck class that inherits from Auto. This would provide access to all the public members and the constructor to the ManlyTruck class. It can refer to the base class using the super keyword and it can extend the definition by adding its own members.

// TypeScript
class Auto {
    engine: string;
    constructor(engine: string) {
        this.engine = engine;
    }
} 

class ManlyTruck extends Auto {
	bigTires: bool;
    constructor(engine: string, bigTires: bool) {
        super(engine);
        this.bigTires = bigTires;
    }
}

TypeScript emits JavaScript that helps extend the class definitions, using the __extends variable. This helps take care of some of the heavy lifting on the JavaScript side.

var __extends = this.__extends || function (d, b) {
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var Auto = (function () {
    function Auto(engine) {
        this.engine = engine;
    }
    return Auto;
})();
var ManlyTruck = (function (_super) {
    __extends(ManlyTruck, _super);
    function ManlyTruck(engine, bigTires) {
        _super.call(this, engine);
        this.bigTires = bigTires;
    }
    return ManlyTruck;
})(Auto);

Interfaces

One of the coolest parts of TypeScript is how it allows you to define complex type definitions in the form of interfaces. This is helpful when you have a complex type that you want to use in your application such as an object that contains other properties. For example, we could define an interface for a Car class such that every car must have an engine and a color like this.

// TypeScript
interface ICar{
    engine: string;
    color: string;
}

class Car implements ICar {
    constructor (public engine: string, public color: string) {
    }
} 

The Car class adheres to the interface ICar because it implements ICar. You can use interfaces on classes but you can also use them to define regular variables types. Notice the code below defines the toyotaCamry variable to use the type ICar.

// TypeScript 
var toyotaCamry : ICar;

This Car sample also uses the alternate syntax in the constructor to define that not only are the engine and color parameters being passed to the constructor but they are also defining a public member of the Car class. This is a nice shortcut syntax since you don;t have to define the members nor set them in the constructor: it does this for you, as you can see in the emitted JavaScript.

// JavaScript
var Car = (function () {
    function Car(engine, color) {
        this.engine = engine;
        this.color = color;
    }
    return Car;
})();

Structure

I can see developers who are familiar with Object Oriented Programming (OOP) feeling very comfortable with TypeScript’s classes and interfaces. There is a lot of value here in getting running quickly and feeling secure that you have written solid code. There is so much more that classes and interfaces can do too, as Dan and I show in our TypeScript course at Pluralsight.

tags: course javascript oop pluralsight typescript
  • http://www.barterlinks.net rickj1

    It’s nice to see Typescript coming out I’m looking forward to your course on Pluralsight it might take some of the buggy out of writing and working with JavaScript ‘I’ve been beating my head against the wall to bring myself up to speed with it up until the other day I thought my investments in C#
    was a waste of time if the whole world is going to go JavaScript and a study came out that said 2.2 billion devices run on C# it’s the #1 language that is a good thing and now with typescript coming on Java script is not going to be so bad life just got better

    Keep up the good work your courses are the best

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1267

  • http://dsheiko.com Dmitry Sheiko

    I would point out that there is no “implements” keywords in TypeScript what developers can expect while working with interfaces. However interfaces in TypeScript are pretty usefull for type annotation and hinting. No mention of arrow expressions, ambient declarations and source files dependencies:
    http://dsheiko.com/weblog/harmony-with-typescript/

    • John

      Dimtry – Thanks for the feedback. I’m not sure what you mean by no “implements” keyword, as you can make a class implement an interface in TypeScript. Also, if you are looking for information on the other topics you mentioned, this is 1 post of a 4 part series on TypeScript. You can find those other topics in the other posts, or in our course for more depth.

      • http://dsheiko.com Dmitry Sheiko

        I meant in Java or let’s say in PHP you use keyword “implements” to refer at an interface like:
        class Foo implements BarInterface

        In TypeScript you define an interface and then use it for type annotation or hinting.

        • John

          TypeScript allows you to define an interface for types, yes. But you can also use it for a class in TypeScript, just as you showed.

          class Car implements ICar {
          ...
          }

          • http://dsheiko.com Dmitry Sheiko

            Hmm, my bad, it really can (just missed it somehow in the specification):
            1.4 Structural Subtyping:
            A class may optionally declare
            that it implements an interface, so that the compiler will check the declaration for structural compatibility
            (http://www.typescriptlang.org/Content/TypeScript%20Language%20Specification.pdf)

            Note that because TypeScript has a structural type system, a class doesn’t need to explicitly state that it
            implements an interface—it suffices for the class to simply contain the appropriate set of instance
            members. The implements clause of a class provides a mechanism to assert and validate that the class
            contains the appropriate sets of instance members, but otherwise it has no effect on the class type.

  • Pingback: Dew Drop – January 7, 2013 (#1,476) | Alvin Ashcraft's Morning Dew

  • Pingback: TypeScript Grammar – Part 2 | John Papa

  • Pingback: New TypeScript Fundamentals Course – Part 1 | John Papa

  • Pingback: Getting Started with TypeScript Now and A New Course Coming Soon! | the pluralsight blog

  • https://github.com/borisyankov/ Boris Yankov

    Naming the interface with an ‘I’ in front, should be avoided.
    There is a good argument against this practice in C#, although it still is the widely used convention and will remain like that for the time being.
    We should not propagate this to TypeScript though.

    • John

      Boris – Thanks for the feedback. This discussion was raised to the TypeScript team too. While it’s a matter of taste, I prefer it so I don’t have any collisions between concrete types and interfaces, which I did run into a few times when I tried not to use the I.

      But it’s purely taste and I recommend picking one way and being consistent.

  • Pingback: Get Started with TypeScript – New Course | John Papa

  • maleki

    hello,
    i see this syntax is very like to action script 3 in adobe flash
    what is your idea ?
    Is there a relation between action script 3 and type script ?

  • Pingback: MSDN Blogs

  • ckruse

    “For singletons I could just as easily use the Module Pattern, and frankly I generally do that with TypeScript.” – could you elaborate a bit more on what you mean by this? Thank you!

    • John

      ckruse – ill have to blog it as its too much for a comment. but in short, create a module and have it return function that returns n object.

  • walkingp

    That’s very useful, thanks.

  • jose velez

    I taken a lot of guidance from your courses and blog. It would love to see your course angular breeze using typescript. I imagine you could do your repo pattern (in typescript) instead of c# code base. I only been able to get this far:
    http://ninetofivecoding.com/2014/04/27/using-typescript-with-angular-js-and-breeze-js-and-entity-framework-code-first-part-2/

%d bloggers like this: