DEV Community

Cover image for TypeScript types and interfaces
Chris Bongers
Chris Bongers

Posted on • Originally published at daily-dev-tips.com

TypeScript types and interfaces

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}`;
};
Enter fullscreen mode Exit fullscreen mode

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

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

type User = {
  firstname: string,
  lastname?: string,
};
Enter fullscreen mode Exit fullscreen mode

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}`;
};
Enter fullscreen mode Exit fullscreen mode

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);
};
Enter fullscreen mode Exit fullscreen mode

Defining an interface

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}`;
};
Enter fullscreen mode Exit fullscreen mode

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

The difference between a type and interface

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;
}
Enter fullscreen mode Exit fullscreen mode

Now the id will be available on this object.

const user: LoggedUser = {
  firstname: '',
  lastname: '',
  id: 34,
};
Enter fullscreen mode Exit fullscreen mode

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

type LoggedUser = User & {
  id: number,
};
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

So which one to pick?

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!

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

Top comments (1)

Collapse
 
andrewbaisden profile image
Andrew Baisden

TypeScript is really on the rise ๐Ÿ˜