DEV Community

Cover image for TypeScript: Interface or Type? Hint: it's in the name
Manuel Artero Anguita 🟨
Manuel Artero Anguita 🟨

Posted on • Edited on

TypeScript: Interface or Type? Hint: it's in the name

It's called TypeScript not InterfaceScript

If you're a purist like I am, you know the debate between 'interface vs. type' can be frustrating. Why is there no official stance on this issue?

I've been using Ts since 2015 and I've been through different phases.

First, I encouraged using interfaces instead of types (unless an Union/Intersection was needed);

...then I reached the stable plateau of "whichever you prefer, it doesn't matter" πŸ˜„.

Till now.

For some time I've been using the type "Any key-value object" a.k.a Record<string, unknown>

If you type something as any key-value object;

function foo(data: Record<string, unknown>) {
  for (const [key, value] of Object.entries(data)) {
    // ...
  }
}
Enter fullscreen mode Exit fullscreen mode

You might reach a dead end if you use interface:

interface Profile {
  name: string;
}

function getProfile(): Profile {
  /* fetch data */
  return Promise.resolve({ name: 'jane' });
}

...
const profile = await getProfile()
foo(profile); // ERROR ❌
// Argument of type 'Profile' is not assignable to parameter of type 
// 'Record<string, unknown>'.
//  Index signature for type 'string' is missing in type 
// 'Profile'.ts(2345)
Enter fullscreen mode Exit fullscreen mode

Our interface { name: string } does NOT fulfill Record<string, unknown>.

I respectful disagree? with typescript here πŸ€“


Now, let's change the thing to type instead:

function foo(data: Record<string, unknown>) {
  for (const [key, value] of Object.entries(data)) {
    // ...
  }
}

type Profile = {
  name: string;
};

function getProfile(): Profile {
  /* fetch data */
  return Promise.resolve({ name: 'jane' });
}

...
const profile = await getProfile()
foo(profile); // βœ… nice
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ The type { name: string } does fulfill Record<string, unknown>


This type of situation isn't specific to Record<string, unknown>' but I don't want to research which Advanced types will work and which won't. So, I've turned to using types -almost- exclusively."


I was shocked to find out that Matt Pocock also went through the same three phases!.

If you haven't heard of Matt, I highly recommend checking him out. He creates high-quality TypeScript content on Youtube (and is a nice guy on Twitter 🦜).


TL;DR: prefer types to interfaces, people on the internet defend types.

Top comments (4)

Collapse
 
raibtoffoletto profile image
RaΓ­ B. Toffoletto

Great artigo, πŸŽ‰ thanks for exposing this!

I'm glad to see I'm not the only one that thinks typescript isn't very consistent in some cases.

Collapse
 
manuartero profile image
Manuel Artero Anguita 🟨

Glad you liked it. I expect they 'fix' this specific issue eventually TBH. Doens't make sense that { key: value } can't be infered as a pair "key - value" xD

Collapse
 
bmorearty profile image
Brian Morearty

Totally agree, it’s very frustrating that the language has these two concepts that are so similar that no one knows which one to use and there’s very little guidance.

Collapse
 
brense profile image
Rense Bakker

I've settled on using interfaces when writing OOP typescript and types in all other circumstances, but I don't have more specific motivation, just that interfaces feel more OOPish 😜