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.
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.
Want to conquer your next JavaScript interview? Download my FREE PDF - Pass Your JS Interview with Confidence and start preparing for success today!