TypeScript types and interfaces

— 5 minute read

permalink

We have seen the basic usage of defining an object in the previous article on TypeScript types. However when we used this object it looked like this:

const getFullName = (user: {firstname: string, lastname: string}): string => {
return `${user.firstname} ${user.lastname}`;
};

Not that there is anything wrong with this, but let's say we need to use this user object again in a saveUser function?

Then we have to copy-paste this same declaration piece all over the place.

And that's where type and interface come in handy.

Defining a type permalink

To define a type, you use it as a variable declaration.

type User = {
firstname: string,
lastname?: string,
};

Then instead of defining these loose objects, we can pass the type to our function.

const getFullName = (user: User): string => {
return `${user.firstname} ${user.lastname}`;
};

And this gives us the option to re-use this type for another function quickly.

const saveUser = (user: User): void => {
return await db.save(user);
};

Defining an interface permalink

A interface is also a declaration of a object and it will look like this:

interface User {
firstname: string;
lastname?: string;
}

const getFullName = (user: User): string => {
return `${user.firstname} ${user.lastname}`;
};

As you can see, not much has changed. We simply replaced the type with an interface declaration.

The difference between a type and interface permalink

Knowing these two, it's keen to see the actual differences between them.

First of all, it's how we declare them. The type has the extra =, which is unnecessary for an interface.

But that's not the main difference.

The main difference is that a type can never change, so we cannot add new properties to a type. And the interface, on the other hand, can be redeclared.

We have our user interface, but we want a LoggedUser object with an extra ID field.

With interfaces, we can extend the existing one like so:

interface LoggedUser extends User {
id: number;
}

Now the id will be available on this object.

const user: LoggedUser = {
firstname: '',
lastname: '',
id: 34,
};

With types we can however do something similar and it will look like this:

type LoggedUser = User & {
id: number,
};

Which comes down to the same effect.

Now let's look at changing the originals and see what happens.

interface User {
firstname: string;
lastname?: string;
}
interface User {
id: number;
}

This will be valid, and the User interface will now have these three fields. However, I would not recommend this as you will get lost as to what kind of properties an interface should have.

On the other hand, the type will simply throw an error if we type the same.

type User = {
firstname: string,
lastname?: string,
};
type User = {
id: number,
};

// Duplicate identifier User

So which one to pick? permalink

It mainly comes down to preference. If you don't have one, stick to the interface until you might need something specific to a type.

For most of the time, an interface will be a perfect fit, and it's super declarative to what something is.

Thank you for reading, and let's connect! permalink

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter