Some thoughts about interfaces and classes in TypeScript

If you’re used to creating classes for “everything” in C# or java it might feel natural to do so in TypeScript too:

class Person {
    name: string;
    address: string;
}

var person = new Person();
person.name = "foo";
person.address = "bar";

Which is fine, but might not be the best tool for the job. If there’s no logic attached to the object, why use a class at all? (Edit: one reason might be performance, see below).

Automatic members from the constructor parameters
You can use this compressed syntax which makes things a bit better

class Person {
    constructor (public name:string, public address:string) {}
}

With a constructor with parameters marked as public, they will automatically be added as class members:

var person = new Person("foo","bar");
alert(person.name + " is at " + person.address);

What about using an interface instead?
Use an interface, and then use a plain object with that interface:

interface Person {
    name: string;
    address: string;
}
var person:Person = {
    address: "foo",
    name: "bar"
}

This does not add any overhead at all to the compiled javascript, and I the syntax used to create the actual object is short and descriptive.

The TypeScript compiler helps you with intellisense and type checking. It even forces you to add values for all members.

If you do not want it to force you to add all members, you can mark them/some of them as optional:

interface Person {
    name: string;
    address?: string;
}

var person:Person = {
    address: "foo"
}

Alternatively you could do a “cast”, when you also get intellisense but don’t need to use all members :

var person = <Person> {
    name: "foo"
}

Also, you can extend an interface if you need to:

interface PersonWithPhone extends Person {
    phone: string;
}

Obviously you cannot implement a constructor or any functions at all in an interface, and you cannot set default values.

Another feature about interfaces is they can be put in definition files (*.d.ts) if you like. That might even be best practice to do so, since it’s only a description of something, and nothing that will produce any javascript code.

Adding members in different places
Typescript interfaces can be defined in multiple places. All members will be added. That is how jQuery plugins definitions works for example. The main jQuery.d.td has the JQuery and the JQueryStatic interfaces available members. And if you add a plugin with a definition file, it too can have definitions with the same interfaces:

interface JQueryStatic {
    myAwesomePluginMethod(): any;
}
interface JQuery {
    myAwesomeChainablePluginMethod(): JQuery;
}

$.myAwesomePluginMethod();
$("body").myAwesomeChainablePluginMethod().hide();

Interface naming convention
Coming from the .Net world I first wanted to name my interfaces with an “I” prefix. But looking in the existing type definition files (both from Microsoft and others), it seems like the convention used is just using an upper case first letter.

What about performance?
In Thoughts on Typescript Isaac Z. Schlueter mentions. If ultimate performance is a goal, as a rule of thumb use classes instead of plain old objects. “If you have more than one of something, use a class; not a “plain old object””.

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s