People often ask me ( online, at work, in skatepark (nope 😂) ), what’s the difference between using type and interface for defining compile time types within TypeScript.

First thing I used to do, was pointing them to TypeScript handbook…

Unfortunately most of the time, they didn’t find the droids that they were looking for ( it’s hidden within Advanced Types section). Even if they found it, the information described there is obsolete ( described behaviour is for typescript@2.0.x ).

Good news everyone! You don’t have to look any further, This post is an up to date description/style-guide about when to use interface vs type alias.

What official documentation says:

“type aliases can act sort of like interfaces, however, there are some subtle differences.”

that’s correct !

What differences?

1. “One difference is, that interfaces create a new name that is used everywhere. Type aliases don’t create a new name — for instance, error messages won’t use the alias name.”

that’s incorrect ! (since TypeScript 2.1)

Let’s define compile time types for Point via interface and type alias and 2 implementation of getRectangleSquare function which will use both interface and type alias for parameter type annotation.

Point defined with interface and type literal

getRectangleArea functions using interface and type alias

Same error reference for both type alias and interface

So errors are same for both:

// TS Error: // Interface: Argument of type '{ x: number; }' is not assignable to parameter of type 'PointInterface'. Property 'y' is missing in type '{ x: number; }'. // Type alias: Argument of type '{ x: number; }' is not assignable to parameter of type 'PointType'. Property 'y' is missing in type '{ x: number; }'.

2. “A second more important difference is that type aliases cannot be extended or implemented from”

Again, that’s incorrect!

We can extend an interface with type alias:

interface extended with type alias

Or use type alias for implementing a Class constraint

class implements type alias

Or use interface extended by an type for implementing a Class constraint

ThreeDimension extends PointType. PointType is an type alias

We can also combine both type alias and interface for implementing a Class constraint

class implements interface and type alias

3. “type aliases cannot extend/implement other types”

Again, that’s incorrect!

Well it’s partially correct but the formulation is miss leading 👀.

You can use interface or any other TypeScript valid type(which has shape of an Dictionary/JS Object, so non primitive types etc…) for type alias extension via intersection operator &

class implements type alias created with intersection

We can also leverage mapped types for various transforms of both interface and type alias.

Let’s make Shape and Perimeter optional via Partial mapped type:

class implements type alias created with intersection and mapped type. perimeter() and area() are optional so we don’t have to implement them within our class

Also weak type detection works correctly:

Weak type detection works as expected

Hybrid Types with both type alias and interface

You might occasionally want to define an object that that acts as both a function and an object, with additional properties.

What we are talking here about, is defining a type for a function ( callable object ) and static properties on that function.

This pattern might be also seen, when interacting with 3rd-party JavaScript, to fully describe the shape of the type.

Hybrid type definition and implementation

It works equally with type alias!

Hybrid type via type alias

There is a very subtle difference though. You will get the particular shape type in IDE instead of reference to the Counter type.

difference between using type alias and interface for hybrid type

What is usually a good idea/practice, is to dissect our hybrid definition in two parts:

callable object (function) type alias

static properties object shape