The Difference between TypeScript Interfaces and Types
Tags: typescript, javascript, webdev, tutorial
Published: 2022-09-18 20:03:48

In TypeScript, you might have noticed you can declare custom types in two different ways. One is with the `interface` keyword, and the other is with the `type` keyword. As such, you may find yourself wondering why there are two ways to do one thing - and you're not alone. I already covered in my guide to [declaring custom types in TypeScript](https://fjolt.com/article/typescript-creating-custom-types), how you can use interfaces and types - but let's look a little bit more into how they differ.

## 1. Interfaces extend syntax is different to types

If we define a type in TypeScript, it is not extendable after the fact. For example, consider this custom type I just made up:
```typescript
type user = {
    name: string,
    age: number
}
```

If, after its been defined, I suddenly realise I want to add an address too, I can do this using the following syntax:
```typescript
type userWithAddress = user & {
    address: string
}
```
With interfaces, we can do the same, but the syntax remains slightly different:
```typescript
interface user {
    name: string;
    age: number;
}
interface userWithAddress extends user {
    address: string
}
```

Now `userWithAddress` contains all the properties of `user`, plus one additional property - that being `address`. 

**The only difference** between these two ways of extending types is how they handle conflicts. For example, if you extend an interface and mention a property that has already been defined, an error will be thrown. For example, **this will not work**:
```typescript
interface user {
    name: string;
}
interface newUser extends user {
    name: number;
}
```

Meanwhile, with `type`, you can do this:
```typescript
type user = {
    name: string
}

type newUser = user & {
    name: number
}
```

While this will not throw an error, it may result in some unexpected results - so you should avoid it where necessary. For example, above, the `name` property is reduced to type `never` - since a type can `never` be both `string` and `number` at the same time. :) 

## 2. Interfaces can be merged - types cannot

Along the same lines, `types` cannot be merged, while `interfaces` can if you declare them multiple times. For example, if we have a type, we can't do something like this:
```typescript
type cat = {
    name: string
}
type cat = {
    color: string
}
```

In fact, **the above code will throw an error**. Meanwhile, with `interface`, we can do that - and it'll merge both declarations. So the example below will create a type called `cat` with both `name` and `color` properties:
```typescript
interface cat {
    name: string;
}
interface cat {
    color: string;
}
```

## 3. Interfaces cannot extend a primative

While we can create a type which can be an alias for a primitive type like `string`, `interface` cannot do this. For example, if you want to create a type called `myName`, which is always of type string, we can do it like this:
```typescript
type myName = string;
```

Here, `myName` becomes an alias for `string` - so we can write `myName` instead of `string`, essentially, anywhere. Meanwhile, `interface` does not have this ability. The following cannot and will not work:
```typescript
interface myName extends string {
    
}
```

## 4. Types can create unions, while interfaces cannot
We can create union types with the `type` keyword, but we can't do that with an interface. For example, here, `userId` can be a `string` or `number`:
```typescript
type userId = string | number
```

Meanwhile, the above cannot be achieved with an `interface`, since interface defines the shape or type of an object.


## Conclusion

As you can see, the main differences between `type` and `interface` kind of depend on the circumstances you use them in. Almost all the features of `interface` are available in `type`, which means you might find yourself more frequently going to `type`. Typically, though, it tends to be based on preference or what works best in your codebase.

In any case, rest assured that it isn't as confusing as you might first think - with both `interface` and `type` effectively being two ways to do the same thing!