When I first started working with TypeScript, I quickly found myself questioning the use of type
and interface
in regards to providing type safety to my code. What is the difference between the two? When should I use one over the other? I decided it was time to get some answers.
After a bit of research, I realized that the two are more similar today than they have ever been. However, there are still some differences that are worth mentioning. Let’s talk about it!
types and interfaces at a high level
Before we take a look at the similarities and differences between a type
and an interface
, let’s first get a good mental model of what the two were intended to achieve in the first place.
The type
keyword in TypeScript is a way for you to provide type aliases to your variables, objects, and functions. These aliases essentially describe what your data is going to look like. You can describe what your data is going to look like by using the core types (e.g. string
, number
, boolean
etc.) or by creating your own custom types. Let’s take a look at a few examples.
The interface
keyword in TypeScript on the other hand is a way for you to describe only what your objects are going to look like. Let’s see an example of interface
.
Right off the bat, you might think that the type
keyword is the more flexible choice of the two when it comes to type safety. Hold that thought. Let’s take a look now at how the two are similar.
Similarities
Let’s say I wanted to provide some type safety for an object, one of the most common use cases for using a type
or an interface
. Turns out they both work pretty much the same, and the syntax is almost identical.
What if I wanted to combine object properties from one type
or interface
into another? We can do that too for both.
I personally prefer the extends syntax as it feels a bit more natural to me.
Want to provide some type safety to your functions? This is also possible with both a type
and an interface
.
I personally prefer using a type here since it reads a bit cleaner, but totally up to you!
A quick note about the above. Earlier I mentioned that an interface can only describe what an object is going to look like, yet here I am describing what a function is going to look like with an interface
. The reason this is possible is because a function technically is an object under the hood.
Finally, if you wanted to create a class that adheres to a certain type safety contract provided by a type
or an interface
, you would be able to do so just fine with both.
That covers most of the similarities of type
and interface
, let’s now take a look at the differences.
Differences
Starting with type
, there are a few things that are possible that you wouldn’t be able to do with an interface
. For example, If you wanted to setup a type alias for just a single core type (e.g. string, number, boolean etc.), this is something that is possible with type
but not with interface
.
Another possibility with type
is that you are able to create a bit more custom type aliases by using unions.
This pretty much sums up the unique offerings of type
. While there may be some more advance features that type
offers that I missed, this should cover the most common use cases.
Moving on to interface
, there is a unique feature called “declaration merging” that you aren’t able to do with a type
.
Wrapping up
To summarize, both type
and interface
provide some nice type safety options for you to choose from depending on your needs. When it comes to describing object shapes which is the majority of my use cases, I prefer to go with an interface
. I personally like that an interface
was designed specifically with this purpose in mind, and is very intentional about it.
However anytime I need to provide type safety for a function, or need a bit more customization for a type alias such as the case with unions, I prefer to go with type
. Both are lovely options for providing type safety, and you really can’t go wrong with using either one!
Top comments (8)
The most important thing regarding
types
is that they support types algebra (not only '|'). That's why I almost never useinterface
-s.could you give an example in which cases i would want the last thing with the
merge
? i dont quite get? lil slow sometimes. i mean i could jsut write it in one interface. you mean smthng like{...spreadRest}
as so to see advantage?A use case for this that I recently encountered is that, there is the Theme interface in material UI library for react and you can import it. After that you can create the same interface with extra custom properties like company specific color palette and standard size configs and declaration merging automatically adds these extended properties to that and your app can consume both the standard stuff in the theme interface and you get intellisense for your custom extensions as well. That's pretty cool in my opinion !
Oh this is a perfect example! Thanks for sharing!
Hey there! You are absolutely right, you can just write everything in one
interface
and personally that is what I usually do. I just wanted to point out that while declaration merging is not something you may use often, it is something that is possible.One thing you missed which I hoped that this post might cover is that types can have self dependencies while interface can't
Hey thanks for mentioning! I'll definitely look into self dependencies with types, I haven't heard of it before! This post was meant to be a little more higher level and cover the most common use cases, since I'm sure there are many other cases exists that I missed.
I dont know "self dependencies" you said above, can u show me what is mean? Im begginer of typescript hehe