Introduction to Interfaces in Typescript
In this video you will learn how to interfaces in Typescript and why it's so difficult to build good entities architecture in Typescript. Also make sure that you watch until the end because I will share my bonus tip of working with Interfaces.
So here I have already setted up empty project for writing typescript. If you missed my video where we installed all needed packages and configured our project I will link it in the description.
First let's look how we can define an object in Typescript and add types to it.
const user = {
name: 'Alex',
age: 30,
}
If we check Typescript types you can see that user has a type of object with properties like name - string and age - number. So without any additional code you have correct types for our object. But let's say that we want to create one more user.
const user2 = {
name: 'Jack',
}
So here we defined only a name and no age. This is exactly the problem that we have in Javascript. We never define full set of properties that our entities need to have. For example in our case we are working with entity User. And we know that in our application each user has name and age properties. So in Javascript at any moment we can forget the property inside or it will be empty and we will try to do some operation and so on.
Typescript gives us a possibility to define how our object should look like.
const user: {name: string; age: number} = {
name: 'Alex',
age: 30,
}
const user2: {name: string; age: number} = {
name: 'Jack',
}
We are doing exactly what we did in previous video. We are specifying all properties that should exist on Users. And this is working fine and we are getting the error
Property 'age' is missing in type '{ name: string; }' but required in type '{ name: string; age: number; }'.
The problem is here that every time when we work with user we need to provide an object with correct properties. And there is a better solution for that. We can move this definition to interface.
interface User {
name: string
age: number
}
So here we defined a User interface. The convention is that every interface is written with capital letter. Inside we are defining all properties of this interface like properties of the object. Now we can refactor our code and use interface everywhere.
const user: User = {
name: 'Alex',
age: 30,
}
const user2: User = {
name: 'Jack',
}
So now here instead of some existing data type we are providing our new data type (interface User). As you can see now we a getting a bit different error.
Property 'age' is missing in type '{ name: string; }' but required in type 'User'
So here we are getting type User which makes it much more understandable and easier to debug. It's not only some random object but an interface that we defined. And this is super crucial to understand. When people start writing Typescript they either don't use lots of interfaces or just create an interface in every place that they need to fix something.
The most difficult part of using Typescript is to plan and building correct types and interfaces in order to develop you project. You should have enough interfaces to cover all cases that you need but not so many that is impossible to support. So I highly recommend first write down all entities and how they communicate with each other. It's actually more advanced stuff than "Typescript for beginners" but just keep it in mind.
As you can see we still have this error that age is not provided. Of course my might provide it but we can also say that age in not required in interface. By default everything that we write in interface is required. If we put question mark after a property it will be optional.
interface User {
name: string
age?: number
}
As you can see now our error is gone because age is optional.
Also it's worth mentioning that interfaces give us the best autocomplete and type check in the world. If we try to access user2 we will immediately see all possible properties that are available.
console.log(user2.age)
In Javascript we can type a property of the object with a mistake but in Typescript it's just not possible because we will immediately get an error from Typescript.
const user2: User = {
namee: 'Jack',
}
Type '{ namee: string; }' is not assignable to type 'User'.
Of course we can add functions inside objects so we can also define then in interfaces like we did with arrow functions previously. If you missed that video go check it first.
interface User {
name: string
age?: number
getMessage(): string
}
const user: User = {
name: 'Alex',
age: 30,
getMessage() {
return 'Hello ' + name
},
}
const user2: User = {
name: 'Jack',
getMessage() {
return 'Hello ' + name
},
}
So here we defined that each User should have getMessage method that returns string.
So now it's time for bonus tip. It's about the naming of interfaces. Actually there is no correct way to name interfaces. You can name them as you want. But the problem starts when you have classes and interfaces. For example if we create class User we will have name collision with our interface because they have the same name.
This is why there are 2 main ways how people name interfaces to distinguish them from other things. 1 way is to prefix them with letter I which basically means interface.
interface IUser {}
another way is not postfix it with entity type. So it's
interface UserInterface {}
In this case you always know with what you are working. I prefer second variant with postfix but it's up to you are team where you are working.
So we successfully learned how to define your own entity types using interfaces.
Want to conquer your next JavaScript interview? Download my FREE PDF - Pass Your JS Interview with Confidence and start preparing for success today!
📚 Source code of what we've done