DEV Community

Shagun Bidawatka
Shagun Bidawatka

Posted on

Why to Choose Types Instead of Interfaces

In TypeScript, both Types and Interfaces are used to define the types of objects. However, they have different uses and features. Both can help developers constrain the types of variables and objects when writing code, thereby reducing errors and improving code readability.

So why Types? Let's discuss this.

Types

In TypeScript, a type lets you define the shape of data. It’s flexible and can be used to create unions, intersections, and more.

type User = {
  name: string;
  age: number;
};

type Admin = User & {
  isAdmin: boolean;
};
Enter fullscreen mode Exit fullscreen mode

Interfaces

An interface is another way to define the shape of an object. It’s more rigid than types and is mainly used for defining object shapes and class contracts.

interface User {
  name: string;
  age: number;
}

interface Admin extends User {
  isAdmin: boolean;
}
Enter fullscreen mode Exit fullscreen mode

Why I Prefer Types

  • Union

Union types let you define a type that can be one of several types. This is handy for function parameters and return types. Here, ID can be either a string or a number, demonstrating the power of union types.

type ID = string | number;

function getUserId(id: ID): string {
  return `User ID: ${id}`;
}
Enter fullscreen mode Exit fullscreen mode
  • String Literals

Literal types let you specify exact values a variable can have. This can be really useful for defining constants or configuration options.

type Direction = 'north' | 'south' | 'east' | 'west';

function move(direction: Direction) {
  console.log(`Moving ${direction}`);
}

move('north');
Enter fullscreen mode Exit fullscreen mode
  • Conditional types

Types allow the creation of conditional types, enabling the selection of types based on conditions

type Check<T> = T extends string ? string : number;

let result1: Check<string>; // result1 is of type string
let result2: Check<number>; // result2 is of type number
Enter fullscreen mode Exit fullscreen mode
  • Intersection

Intersection types allow you to combine multiple types into one. This is especially useful for creating complex type compositions.

type Person = {
  name: string;
  age: number;
};

type Employee = {
  employeeId: number;
};

type EmployeeDetails = Person & Employee;

const employee: EmployeeDetails = {
  name: 'Dev',
  age: 30,
  employeeId: 12345,
};
Enter fullscreen mode Exit fullscreen mode

Choosing between types and interfaces ultimately depends on your specific use case and personal preference. However, understanding the strengths of each can help you make more informed decisions and write better TypeScript code.

Top comments (18)

Collapse
 
rita profile image
Rita

I personally prefer using interfaces because of their cleaner syntax (though this is subjective). On a subconscious level, interfaces feel like contracts or shapes of data, while types seem more like value descriptions of variables. Therefore, I use interfaces for object-like structures and types for basic strings, numbers, etc. Sometimes, I also use types when I need unions or something similar.

Thanks for the post! I didn't know about conditional types 👍

Collapse
 
kwoodgmr profile image
kwood-gmr

Your statement concerning interfaces ("It’s more rigid than types ") is **not **correct. Interfaces have a different kind of flexibility. For instance: you can add to an interface in another location. Also, you can specify that something implements multiple interfaces. The vast majority of the time the two can be used interchangeably. When you find you need features of one over, often you can simply change from one to the other.

It is fine to have a preference, but please put no more stock into your preference for one over the other than somebody's preference of one flavor of ice cream over another. (Or even that some don't like ice cream as crazy as that seems to me.)

Collapse
 
matatbread profile image
Matt

Interfaces support "augmentation", where you can extend an interface declared elsewhere. They are also evaluated "lazily" by tsc and so can be used for some recursive and circular declarations that types can complain about

To focus on the basic syntax is to miss the point. A simple reading of the typescript docs is time better spent than reading this article

Collapse
 
perer876 profile image
Oscar Arámbula

Everything you can do with an interface, you can do using a type, but not vice versa. The approach I have seen is to use an interface whenever possible and use types otherwise. Why? I think of it like it is more "dynamic" using types

Collapse
 
mayowa_akoni_c5148d3bff28 profile image
Mayowa Akoni • Edited

While one could use Interface to define the shape of a data, it's better to think about it as a contract.
Proper use of contract could help build loosely coupled modules.
Types help to build data type of almost any shape.

Collapse
 
joaozitopolo profile image
Joao Polo • Edited

Good informations about "types". I prefer "type" also, but I saw several companies using interface for data coming from APIs.
I think one real difference is that interfaces could be inspected on runtime. It's not possible for type.
-- EDIT --
I done a few tests and it's not true. I couldn't inspect interfaces on runtime. Maybe it has no real differences, only two ways to do the same.
I prefer type too because I think it has a better syntax.

Collapse
 
perer876 profile image
Oscar Arámbula • Edited

Neither type nor interface can be checked at runtime. TypeScript removes them

Collapse
 
adarshkunwar profile image
Adarsh Kunwar

hi Joao, what do you mean by inspecting it on runtime?

Collapse
 
joaozitopolo profile image
Joao Polo

If you have an object coming from a json, for example, you can inspect if it is compatible with some interface. But it's not possible to see if this object is compatible with a type.

Thread Thread
 
joaozitopolo profile image
Joao Polo

Um, I had a second look on it, maybe it's not possible, not using "instanceOf" as I expected.
Then, I should think the difference is if you use classes, because classes could implements interfaces (not types), but... Just done a test and you can use "implements" for type also.

Collapse
 
michelangelo17 profile image
Michelangelo Markus

Am I the only one who saw that union example for ID and immediately felt rage? LOL

That's literally the textbook example for using TypeScript over JavaScript in the first place. Haha

I get there are good uses for it but that example just is like, why even bother then?

Collapse
 
shagun profile image
Shagun Bidawatka

Taking your point, will mention good usecase examples in further blogs.
I prefer to keep it simple so that it's easy to understand the main thing which is tried to convey.

Collapse
 
michelangelo17 profile image
Michelangelo Markus

Yeah, I did get that was probably the logic, just had an immediate visceral reaction to it. But that's why I added the "lol", not truly trashing it, just chuckling over how the sight of it made me feel.

Collapse
 
ebcefeti profile image
E. B. Cefeti

One thing I struggle to wrap my brain around is, how much of the weakness in interfaces isn't so much an issue with the Interface model/pattern as much as
an issue specifically with the Typescript implementation.

Collapse
 
larastewart_engdev profile image
Lara Stewart - DevOps Cloud Engineer

Interfaces are not just meant to be replaced with types; they have their own advantages. Use interfaces most of the time when the types of the variables are not changing much and you don’t need to extend them. If the types are likely to change, then using types is a good choice.

Everything has its purpose. Knowing when to use one over the other is what makes you a better programmer, rather than always choosing one over the other.

Collapse
 
chris_sd_b9194652dbd4a1e profile image
Chris S-D

So there is one thing (that I know of) that can be done with an interface that can't be done with type, which is to be able to extend an existing interface in a different location. I question that practice as that seems likely to add potential confusion about what the contract is.

Other than that, so far, I've been able to do everything with types that I can accomplish with interfaces and a few things I can't. For that reason, I personally find it less taxing on my brain than having to decide when I'm going to use one over the other.

In short, my reasoning for preferring types over interfaces is that I can avoid using interfaces all the time but I can't avoid using types all the time. It keeps things nice and simple for me to always have a single answer to the question. "Should I use a type or interface here?"

Collapse
 
benbenbenbenbenben profile image
Benjamin Babik • Edited

Classes can implement interfaces:

interface Bar { bar: string }
class AcmeFooBar implements Bar {
   bar = "hello"
}
Enter fullscreen mode Exit fullscreen mode