Differences between interface and type in TypeScript 
Tags: typescript, javascript
Published: 2020-08-15 18:38:16

Sometimes you find yourself using TypeScript and wonder whether you should pick and `interface` or a `type`.

The keyboard cursor is blinking.

The clock is ticking.

And you haven't written the `t` for `type`, or the `i` for `interface` yet.

If this has happened to you, I have something to tell ya': at the end of this post, you'll know exactly which one to choose and never hesitate again in this specific situation.

## Differences

In general, both declarations are pretty much interchangeable. Albeit there are two big differences:

1. `interface` can be augmented through _declaration merging_, whereas `type` can't
2. `type` can extend _union types_, whereas `interface` can't

Let's dissect these two points:

### Diference #1

What's declaration merging? If you ever used `Ruby`, you can do these kind of `class` augmentations:

```ruby
class Dog
  def bark
    puts 'woof-woof!'
  end
end

# A few lines of code below

class Dog
  def bark2
    puts 'arf-arf!'
  end
end
```

This is called [_monkey patching_](https://en.wikipedia.org/wiki/Monkey_patch). You can basically re-open a `class` and add more methods to it, or even override them.

In TypeScript there's a similar concept called [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html):

> “declaration merging” means that the compiler merges two separate declarations declared with the same name into a single definition. This merged definition has the features of both of the original declarations. Any number of declarations can be merged; it’s not limited to just two declarations.

For the scope of the post, we are only interested in _interface merging_.

What can we do with it?

In a similar way as monkey patching, we can join partial interface declarations with the same name into a single one.

For example, we can have:

```typescript
interface Dog {
  bark(): void
}

interface Dog {
  bark2(): void
}
```

And then, using it as a single merged interface:

```typescript
const doggyDog: Dog = {
    bark() {
        console.log('woof-woof!')
    },
    bark2() {
        console.log('arf-arf!')
    }
}
```

If we use `type`, we'll get a duplication error:


```typescript
type Dog = {
    bark(): void
}

type Dog = {
    bark2(): void
}
```

```
| Duplicate identifier 'Dog'.
```

### Diference #2

The ability of `type` is that it can extend [union types](https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html).

What are union types?

If we think types as sets of values, we might want values that belong to the type `A`, and perhaps also to another type `B`.

We can achieve that in TypeScript unifying these two types using the vertical bar `|` as `A | B`.

With this, we've created a new type whose values belong to both sets.

For instance, if we have:

```typescript
type Dog = {
  bark(): void
}

type Cat = {
  meow(): void
}

type CatDog = Cat | Dog
```

Then, we can extend this `type` declaration:

```typescript
type Pet = CatDog & {
    name: string
}
```

On the other hand, if we use `interface` it'll complain:

```typescript
interface Pet extends CatDog {
  name: string
} 
```

```
| An interface can only extend an object type or intersection of object types with statically known members.
```

For more info about this error you can check this [GitHub issue](https://github.com/microsoft/TypeScript/issues/27890).

## Conclusion

OK, so now I know the differences... but which one should I use?

I'd say it'll depend on your particular case.

If you want to have types that are rather complex and flexible, then you should use `type`.

If you want more readability in the code, avoid extending union types, or you are prototyping code that might require augmentation throughout the codebase, then you should consider using `interface`.

From my experience, I'm currently working on a project that started using `type` for everything, and we are stick to it without needing to use `interface` at all.

Remember that, in most cases, `type` is more capable than an `interface`.

### References

- https://www.typescriptlang.org/docs/handbook/declaration-merging.html
- [Effective TypeScript Book](https://effectivetypescript.com/)
- https://stackoverflow.com/questions/37233735/typescript-interfaces-vs-types