Typescript Type vs Interface - Which One Is Better?
Typescript Type vs Interface - Which One Is Better?

In this post you will learn the difference between type and interface inside Typescript.

When people start learning Typescript this is always a huge question. Is it better to use type or an interface because they are extremely similar.

Data representation

If you want to represent some data in Typescript people are typically using interfaces.

interface User {
  id: number
  name: string
  email: string
}

const user: User = {
  id: 1,
  name: 'foo',
  email: 'foo@gmail.com'
}

Lots of tutorials about Typescript are using interfaces for examples. They say if we have some entity then we need to use interface word like this.

Interface defines a contract that our object must fulfil.

But now let's try to fully replace interface with a type.

type User = {
  id: number
  name: string
  email: string
}

const user: User = {
  id: 1,
  name: 'foo',
  email: 'foo@gmail.com'
}

There are zero differences here. Both interface and type are working in the same way for this scenario. We get the same validation and possibilities.

With Type we defined a shape of date. We can use it to define not only objects but any types of data.

type ID = string

Interfaces on the other hand are only related to the entities like objects.

Extend and intersection

As some point of development we want to create a new interface based on existing User.

interface Admin extends User {
  permissions: string[]
}

const user: Admin = {
  id: 1,
  name: 'foo',
  email: 'foo@gmail.com',
  permissions: ['dev']
}

Here we used reserved word extends which works like extends inside classes. It means that we take all properties from User interface and they are not available in Admin interface. Additionally we added permissions property to our Admin.

This was extending. But what is intersection?

type Admin = User & {permissions: string[]}

const user: Admin = {
  id: 1,
  name: 'foo',
  email: 'foo@gmail.com',
  permissions: ['dev']
}

This and operator between User and an object is an intersection. It means that we want to merge all User fields with all fields from the object on the right. As you can see with intersection we achieve the same result like with extending. There is no difference between type and interface here.

Function overloading

But here is the main difference between types and interfaces.

interface User {
  id: number
  name: string
  email: string
  getPermission(): string
}

interface Admin extends User {
  permissions: string[]
  getPermission(): string[]
}

Here we are extending Admin from our User and we try to override getPermission method and tell that we must return different data type there. It won't work. We directly get an error.

Interface error

With types on the other hand it is completely possible and it implements function overloading in this case.

type User = {
  id: number
  name: string
  email: string
  getPermission: (id: string): string
}
type Admin = User & {
  permissions: string[],
  getPermission: (id: string[]): string[]
}

const user: Admin = {
  id: 1,
  name: 'foo',
  email: 'foo@gmail.com',
  permissions: ['dev'],
  getPermission: (id: string|string[]): string|string[] => {
    return (typeof id === "string" ? id : [id]) as string[] & string;
  }
}

Here we can defined getPermission through intersection with different data types and we won't get any errors. But then we must implement this function with function overloading so we must cover all possible cases which is string or string[] for this function.

Classes

The next use case where we can use both interface and type is implementation of classes.

interface User {
  id: number
  name: string
  email: string
}

class Student implements User {
  id = 1
  name = 'foo'
  email = 'foo@gmail.com'
}

Here we force our class to implement all properties from this interface by using implements keyword. But in exactly same way we can use a type.

type User = {
  id: number
  name: string
  email: string
}

class Student implements User {
  id = 1
  name = 'foo'
  email = 'foo@gmail.com'
}

Results

So what should you use now? Type or interface? In 90% of the cases you can use them interchangeably. If you just need to create some entity you can use either interface or type. It is a matter of personal preference. I really like to use interface for all object typed values.

If you need to define something else and not an object you don't even have a choice. It can be only type. If you get the result of some Typescript helpers like Pick or Omit you will also get a type.

And actually if you want to improve your Typescript knowledge and prepare for the interview I highly recommend you to check my course Typescript Interview Questions.