142

What is the different between Typescript Interfaces and Classes? When do I use a Class? When do I use Interfaces? What are the advantages of them?

I need to create some kind of types for an http-request to my backend server (Doing it with Angular 2), like : },

"fields": {
  "project": {
      "id": "10000"
  },
  "summary": "something's wrong",
  "issuetype": {
      "id": "10000"
  },
  "assignee": {             // not neccesary required
      "name": "homer"
  },
  "reporter": {
      "name": "smithers"
  },
  "priority": {            // not neccesary required
      "id": "20000"
  }
}

What should I use for building these models? Thank you!

Willem van der Veen
  • 33,665
  • 16
  • 190
  • 155
Emre Öztürk
  • 2,660
  • 4
  • 16
  • 19
  • 4
    I would suggest you do some reading on OOP principles first.. and maybe have a read trough the typescript handbook.. the interfaces and classes chapters ought to be of help. :) – toskv Dec 05 '16 at 11:21
  • better you refer this link https://johnpapa.net/typescriptpost3/ – Amruth Dec 05 '16 at 11:28
  • 9
    If you only need to have type safety for this structure you posted then use interfaces. If you want to have methods for those instances then use classes – Nitzan Tomer Dec 05 '16 at 11:28

9 Answers9

152

2019: Update on Differences and Usages

First, there is the obvious difference: syntax. This is a simple, but necessary to understand difference: Interface properties can end in commas or semi-colons, however class properties can only end in semi-colons. Now the interesting stuff. The sections about when to use and not to use may be subjective - these are the guidelines I give people on my team, but it is possible that other teams will have other guidelines for valid reasons. Feel free to comment if your team does it differently, I would love to learn why.

Interfaces: Allow for defining a type that will be used during design and compile time for strong typing. They can be "implemented" or "extended" but cannot be instantiated (you can't new them). They get removed when transpiling down to JS so they take up no space, but they also cannot be type checked during runtime, so you can't check if a variable implements a specific type at runtime (e.g. foo instanceof bar), except by checking the properties it has: Interface type check with Typescript.

When to use interfaces: Use them when you need to create a contract of the properties and functions for an object that will be used in more than one place in your code, especially more than one file or function. Also, use when you want other objects to start with this base set of properties, such as having a Vehicle interface that multiple classes implement as specific types of vehicles, like Car, Truck, Boat (e.g. class Car implements Vehicle).

When not to use interfaces: When you want to have default values, implementations, constructors, or functions (not just signatures).

Classes: Also allow for defining a type that will be used during design and compile time for strong typing, and, additional, can be used during runtime. This also means that the code is not compiled out, so it will take up space. This is one key difference mentioned by @Sakuto, but has more implications than just space. It means that classes can be typed checked, retaining the understanding of "who they are" even in the transpiled JS code. Further differences include: classes can be instantiated using new and can be extended, but not implemented. Classes can have constructors and actual function code along with default values.

When to use classes: When you want to create objects that have actual function code in them, have a constructor for initialization, and/or you want to create instances of them with new. Also, for simple data objects, you can use classes for setting up default values. Another time you would want to use them is when you are doing type checking, though there are workarounds for interfaces if needed (see the interface section OS link).

When not to use classes: When you have a simple data interface, do not need to instantiate it, when you want to have it implemented by other objects, when you want to simply put an interface on an existing object (think type definition files) or when the space it would take up is prohibitive or unwarranted. As a side note, if you look in .d.ts files you will notice that they only use interfaces and types, and thus this is completely removed when transpiled to TS.

Final note, there are two other options than just classes and interfaces, the first is something called a "type", which is pretty similar to an interface, but check this SO post, specifically the 2019 Update answer: Typescript: Interfaces vs Types. The last option is to go functional programming style (not OOP) with TS.

For the full story with examples visit PassionForDev.com and more good reading on classes vs. inheritance with examples visit https://jameshenry.blog/typescript-classes-vs-interfaces/.

Jeremy
  • 2,259
  • 3
  • 16
  • 18
  • 3
    I just discovered something interesting with the instanceof for classes, you must create a new instance of a class in order to have it be able to check for the type, not just use it as a type. This may seem obvious when you think about it, but when I made the mistake when I tried to write an example. Thus `const classExample1: ClassExample = { status: 200 }` will not work with instanceof but `const classExample2 = new ClassExample()` will. – Jeremy Apr 05 '19 at 18:18
  • What about casting @Jeremy? ie `{} as User` – Ben Racicot Apr 10 '19 at 14:03
  • @TR3B, are you asking what happens in TS when you do `{} as User casting`? What is `User`? That would tell TS whether it is an interface or a class - not sure if I understood your question though. – Jeremy Apr 16 '19 at 19:39
  • 1
    @TR3B, I thought about this some more, and when you do `{} as User`, you are effectively treating the type as an Interface, even if it is a class. If it is a class, it will only be used by type-casting and will not receive any of the functionality of the class, treating it like an Interface just defining the type structure. – Jeremy Apr 17 '19 at 23:52
  • @Jeremy I'm quite new to TS but wanted to add to your casting comment. I'm building an API and ran into an issue where I had less properties in an interface than in the source object (I queried it from the database, so the source type was a User model class which has properties `id, username, password`). I want to abstract the DB logic from the app and create a DTO without the password and when I cast to that DTO, the `password` field remains in the object (both with class and IF). But when you create a class instance with `new`, then you can use which fields you want with the constructor. – V. Samma May 11 '20 at 13:32
  • Hi @V.Samma, sorry I took so long in my response, I just noticed your comment. I didn't quite get what you were trying to convey in your last "But" statement. What object are you instantiating? The DTO or the User object? – Jeremy Nov 03 '20 at 04:02
  • Hi @Jeremy, I was comparing instantiating the DTO object with interface by casting vs with class by using the `new` keyword and passing only relevant data to the class constructor. That when you want to cast the `User` object to the corresponding DTO which has less fields in its type declaration, you will still have all the fields present in the DTO that the `User` object had. The only way to only fill the exact properties the DTO has is to explicitly fill them, either by creating a class object through its constructor or creating the DTO object by manually writing out all the properties. – V. Samma Nov 04 '20 at 11:09
  • Great explanation! The only thing I want to correct is that interfaces cannot be extended `Cannot extend an interface 'Vehicle'. Did you mean 'implements'?ts(2689)` – boludo kid Jun 24 '22 at 16:09
28

According to Angular 2 styleguide it's recommended to use Class over Interface for the typing. The main difference is that class will persist when compiled while Interface are purely removed since they do not serve any usage.

Just stay consistent over the whole project, and prefer the styleguide approach with class, who know, maybe one day you will need to add method to your models.

Check answer below for more details: https://stackoverflow.com/a/55505227/5463904

LoïcR
  • 4,940
  • 1
  • 34
  • 50
  • 3
    angular style guide doesn't specify the reason for using `class` over `interface`. it says to "consider" your requirement. read more here : https://github.com/angular/angular/issues/19632 – candidJ Mar 13 '18 at 11:44
  • 3
    "who know, maybe one day you will need to add method to your models." Interfaces support methods as well. – Michael Gummelt May 23 '19 at 17:49
14

Simply Class is to create objects and Interface assists you what these objects should contain.

Class is like a blueprint/template using which we can create objects. Interface is like a contract on which a Class has to agree on to implement that Interface or define what this blueprint should contain.

A simple class:

class Car {
    engine: string; // 'var' is not used;

    constructor(engine: string) { // This is how we create constructor
        this.engine = engine;
    }

    display(): void { // 'function' keyword is not used here.
        console.log(`Engine is ${this.engine}`); // just a log.
    }
}

var objCar = new Car('V8'); // creates new onject
objCar.display(); // output: Engine is V8
console.log(objCar.engine); // output: V8 (accessing member here)

A simple Interface:

    interface IPerson { // This is how we create an interface.
        firstName: string, // use commas to separate.
        lastName: string, // In classes we use semi-colon to separate.
        displayDetails: (number) => string
    }

    // We are going to store 'interface object' in a variable.
    // i.e. we are implementing interface with variable(not class!!)
    var customer: IPerson = {

        firstName: 'jose jithin', // 'implements' variables
        lastName: 'stanly',

        // Now method implementation.
        // Note: the syntax of 'displayDetails' maybe a bit confusing (given below)
        // as two colons are used.
        // It specifies a return type(string) here for this method. 
        displayDetails: (rank): string => { return `This person has rank ${rank}. ` }  

        // It can be rewritten as following too.
        displayDetails: (rank) => { return `This person has rank ${rank}. ` };
        // i.e. return type need not be specified, just like a normal method definition syntax.
    }

    console.log(customer.firstName); // output: jose jithin

    console.log(customer.lastName);  // output: stanly

    console.log(customer.displayDetails(1)); // output: This person has rank 

I have detailed on Class and Interface with my article. This might help you to understand.

Pang
  • 9,564
  • 146
  • 81
  • 122
Jose
  • 2,479
  • 1
  • 20
  • 17
5

Interfaces

  • Describe how an object should look
  • Exists compile time only, with the sole purpose of type checking

Classes

  • Used as a blueprint from which to instantiate/produce objects
  • Can implement an interface which means it has to implement at least all of the properties/methods from the interface

Example:

interface Person {
    name: string;
    id: number;
    doStuff: () => void;
}

// implements Person says: You have to at least implement these things
// which are located on the person interface 
class employee implements Person {
    constructor(public name: string, public id: number){}

    doStuff () {console.log('Doing stuff')}
}

// interfaces can also describe variables and parameters
const p1: Person = {
    name: 'foo',
    id: 34,
    doStuff () {console.log('Doing stuff')}
}
Willem van der Veen
  • 33,665
  • 16
  • 190
  • 155
4

Use typescript for making a Data model instead of class as compiler will not generate any corresponding JavaScript code for an interface at run time. Whereas if you use a class for merely making a data model then compiler will create corresponding JS code for it hence will consume memory.

A snippet from Angular's style guide: https://angular.io/guide/styleguide#interfaces

"Consider using a class instead of an interface for services and declarables (components, directives, and pipes)."

"Consider using an interface for data models."

Community
  • 1
  • 1
Abhishek
  • 236
  • 3
  • 3
2

I am using angular past 2 years and in simple words when I want to add any behavior to my object I use class for example in any class I want to add get method which return processed data, and when there is no behavior added to object and I want to directly access object I will use interface.. Using class if you define constructor you restrict user to define certain variable to initialized before constructing any object.

Kushagra Misra
  • 461
  • 1
  • 7
  • 15
0

I have found that type safety is not as strong when using classes instead of interfaces, specifically with function signatures that are passed as a prop in React.

slimeygecko
  • 630
  • 7
  • 13
0

So there are multiple differences in class and interface.

Few of those are :

Definition
TypeScript Class is a template which holds methods,variables and provides a skeleton to object. TypeScript Interface is a blueprint which will tell a deriving class what to implement.

Practical Usage

Class : To design a skeleton of modules functionality wise
interface : To hide a complexity from external accessing resource and securing core logic

Instantiable

Class: We can Instantiate class using its object
Interface: We can not instantiate interface

you can find more difference at : https://codetopology.com/scripts/typescript/typescript-interface-vs-class/

Ankit21ks
  • 468
  • 1
  • 7
  • 22
0

Interfaces in TypeScript serve two purposes:

  1. Blueprint for classes (e.g., class Foo implements IFoo)
  2. “Typed Objects” (e.g., let foo: IFoo = { … })

#1 is the “classic” purpose, seen in Java, C#, et al.: an interface just describes what a class should look like. It isn’t directly instantiated or anything.

#2 is something I, at least, have only seen in TypeScript: it’s basically a compile-time-checked dictionary.

My experience has been that #2 leads to maintenance problems: that simple dictionary you create today may eventually have use for methods, in which case you have to alter all the callers, which enlarges testing scope.

I RECOMMEND: Avoid pattern #2 for things public in favour of classes. It’s fine as an internal compile-time check, but you’ll advantage your code’s future maintainers by facilitating addition of methods. You may never need the methods, sure, but when you do you’ll be glad you left yourself the option.