2019: update on differences and uses
First, there is an obvious difference: syntax. This is simple, but necessary to understand the difference: interface properties can end with semicolons or semicolons, however class properties can end only with semicolons. Now interesting things. The sections on when to use and not to use can be subjective - these are recommendations that I give to people on my team, but it is possible that other teams will have different recommendations for valid reasons. Feel free to comment if your team does it differently, I would like to know why.
Interfaces : allow you to determine the type that will be used during development, and compilation time for strong typing. They can be "implemented" or "extended", but they cannot be created (you cannot new them). They are deleted when ported to JS, so they do not take up space, but they also cannot be checked for type at runtime, so you cannot check if a variable implements a certain type at runtime (for example, foo instanceof bar ), except checking the properties that it has: Checking the type of interface using Typescript .
When to use interfaces : use them when you need to create a contract of properties and functions for an object that will be used in several places of your code, especially in several files or functions. Also use when you want other objects to start with this basic set of properties, for example, with the Vehicle interface, which several classes implement as specific types of vehicles, such as Car , Truck , Boat (for example, class Car implements Vehicle ).
When not to use interfaces : When you want to have default values, implementations, constructors or functions (and not just signatures).
Classes : also allow you to determine the type that will be used at design time and compilation time for strong typing and, in addition, can be used at run time. It also means that the code is not compiled, so it will take up space. This is one key difference mentioned by @Sakuto, but it has more consequences than just space. This means that classes can be typed, while retaining an understanding of who they are even in the transmitted JS code. Further differences include: classes can be created using new and can be extended, but not implemented. Classes can have constructors and the actual function code along with default values.
When to use classes : when you want to create objects that have valid function code, there is a constructor for initialization and / or you want to instantiate them using new . Also for simple data objects, you can use classes to set default values. Another time you want to use them is when you perform type checking, although there are workarounds for interfaces if necessary (see the OS section of the link section).
When not to use classes : when you have a simple data interface, you donโt need to instantiate it when you want it to be implemented by other objects, when you just want to put the interface into an existing object (think of type definition files) or when space, which it takes is prohibitive or unreasonable. As a side note, if you look at the .d.ts files, you will notice that they only use interfaces and types, and thus this is completely removed when passed to TS.
Last note , there are two other options besides classes and interfaces, the first of them is called โtypeโ, which is very similar to the interface, but look at this SO post, in particular, the answer to the 2019 update: Typescript: Interfaces vs Types . The final option is to use a functional programming style (not OOP) with TS.
For a complete history with examples, visit PassionForDev.com, and for more information on classes and inheritance with examples, visit https://jameshenry.blog/typescript-classes-vs-interfaces/ .