Interface and class in TypeScript Interface and class in TypeScript javascript javascript

Interface and class in TypeScript


Consider that in Javascript, data is often exchanged as plain objects, often through JSON:

let data = JSON.parse(someString);

Let's say this data is an array of User objects, and we'll pass it to a function:

data.forEach(user => foo(user))

foo would be typed like this:

function foo(user: User) { ... }

But wait, at no point did we do new User! Should we? Should we have to write a class User and map all the data to it, even though the result would be exactly the same, an Object with properties? No, that would be madness just for the sake of satisfying the type system, but not change anything about the runtime. A simple interface which describes how the specific object is expected to look like (to "behave") is perfectly sufficient here.


I also came to Typescript from a C# background and have wondered the same things. I was thinking along the lines of POCOs (is POTO a thing?)

So what interfaces are meant for in TypeScript?

The Typescript Handbook seems to say that interfaces are meant for "defining contracts within your code".

Why do people use interfaces in TypeScript like we use classes in C#?

I agree with @deceze's answer here.

John Papa expands on the subject of classes and interfaces on his blog. He suggests that classes are best suited for "creating multiple new instances, using inheritance, [and] singleton objects". So, based on the intent of Typescript interfaces as described in the Typescript Handbook and one man's opinion, it would appear that classes are not necessary to establish contracts in Typescript. Instead, you should use interfaces. (Your C# senses will still be offended.)

Interfaces should be properly used in TypeScript: to establish contracts of behavior, or to define properties and object should have?

If I understand the question, you are asking if interfaces should establish contracts of behavior or contracts of structure. To this, I would answer: both. Typescript interfaces can still be used the same way interfaces are used in C# or Java (i.e. to describe the behavior of a class), but they also offer the ability to describe the structure of data.

Furthermore, my coworker got on me for using classes instead of interfaces because interfaces produce no code in the compiler.

Example:

This Typescript:

class Car implements ICar {    foo: string;    bar(): void {    }}interface ICar {    foo: string;    bar(): void;}

produces this Javascript:

var Car = (function () {    function Car() {    }    Car.prototype.bar = function () {    };    return Car;}());

Try it out


Interfaces in typescript are similar to interfaces in C# in that they both provide a contract. However opposed to C# interfaces which only contain methods typescript interfaces can also describe fields or properties that objects contain. Therefore they can also be used for things which are not directly possible with C# interfaces.

A major difference between interfaces and classes in typescript is that interfaces don't have a runtime representation and there won't be any code emitted for them. Interfaces are very broadly usable. For example you can use object literals to construct objects with satisfy an interface. Like:

let user: User = {  name: 'abc',  address: {    street: 'xyz',  },};

Or you can assign any data objects (e.g. received through JSON parsing) to an interface (but your pre-checks should assert that it's really valid data). Therefore interfaces are very flexible for data.

On the other hand classes have a type associated at runtime to them and there is code generated. You can check the type at runtime with instanceof and there's a prototype chain set up. If you define User as a class it won't be a valid user unless you call the constructor function. And you can't just define any kind of suitable data to be a User. You would need to create a new instance and copy the properties over.

My personal rule of thumb:

  • If I'm dealing with pure data (of varying sources) I use interfaces
  • If I'm modelling something which has an identity and state (and probably attached methods to modify the state) I'm using a class.