The Difference Between Types (Type Aliases) And Interfaces in TypeScript
Tags: typescript, javascript, frontend, webdev
Published: 2023-02-22 05:28:37

---
title: The Difference Between Types (Type Aliases) And Interfaces in TypeScript
published: true
description: One of the most popular questions about TypeScript concerns the difference between type aliases and interfaces. This article describes it in detail and highlights specific use cases for each feature.
tags: #TypeScript, #JavaScript, #FrontEnd, #WebDevelopment
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uc369jt4dc5y2ndgpafo.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2023-02-22 05:12 +0000
canonical_url: https://blog.savetchuk.com/the-difference-between-types-type-aliases-and-interfaces-in-typescript
---

Today, more and more people and companies are using TypeScript. It is among the top 10 programming languages in the [PYPL index](https://pypl.github.io/PYPL.html). And this is not surprising, since TypeScript allows you to catch many errors at compile time, not at runtime, that is before they are released to production.

![Top 10 programming languages according to PYPL Index as of February 2023](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fsf3moy58reboy72sz0k.png)

*Top 10 programming languages according to PYPL Index as of February 2023.*

Some of you who decide to try TypeScript might get confused with type aliases and interfaces because they are both similar and used to define the shape and structure of values in a statically typed way. This means that it is possible to describe the same object using a type alias or an interface:

```typescript
// Option #1: using a type alias
type Person = {
  firstName: string;
  lastName: string;
  age: number;
};

// Option #2: using an interface
interface Person {
  firstName: string;
  lastName: string,
  age: number;
};
```

You might be asking yourself why we have two options for describing the `Person` object instead of one. And are there any differences or specific use cases between type aliases and interfaces? Yes, and you will find out about them in a moment.

Before we begin, I should mention that the correct term for a **type** is **type alias**, but for simplicity, I will use those two terms interchangeably.

## Difference #1: Objects and Functions

Both types and interfaces can be used to describe the shape of an object or a function signature. However, the syntax is different. A type is defined using the `type` keyword, followed by the name, an equals sign and the type definition:

```typescript
type SampleObject = {
  a: string;
  b: string;
};
```

An interface is defined using the `interface` keyword, followed by the name and the interface definition in curly braces:

```typescript
interface SampleObject {
  a: string;
  b: string;
};
```

As you can see, there is not much difference in syntax between the two examples. However, when we want to define a function signature, the difference becomes more noticeable:

```typescript
// Using the "type" keyword
type SampleFunction = (param1: string, param2: number) => boolean;

// Using the "interface" keyword
interface SampleFunction {
  (param1: string, param2: number): boolean;
}
```

In practice, either approach can be used to define a function in TypeScript, and the choice between them often comes down to personal preference or project standards.

## Difference #2: Other Types

**Unlike an interface, the type alias can be used to create named types for all other types including:**

* **primitives**
    
* **unions (union types)**
    
* **tuples**
    
* **mapped types**
    

### Primitives

Just in case, I will remind you that there are six primitive types in JavaScript and TypeScript: boolean, number, string, null, undefined, and symbol. Here is an example of how to represent primitives in TypeScript using the `type` keyword:

```typescript
type Name = string;
type Age = number;
type IsStudent = boolean;
```

With interfaces, you cannot directly define a named type for a primitive type.

### Unions

A variable with a union type can hold a value of any of the constituent types. Union types can be formed by combining two or more other types, separated by a vertical bar (`|`).

```typescript
// Example #1: union type that allows a variable to hold 
// one of the three specified string literal values.
type SampleType1 = 'Coffee' | 'Tea' | 'Water';

// Example #2: union type that allows a variable to hold 
// a value that is either a string or a number.
type SampleType2 = string | number;

// Example #3: union type that allows a variable to hold
// any of the values that are allowed by SampleType1 or SampleType2
type SampleType = SampleType1 | SampleType2;
```

Same as with primitives, you cannot directly define a union type using the `interface` keyword, however, it is possible to have a union type as an object property:

```typescript
interface SampleObject {
  myProperty: string | number;
}
```

---

**There are some limitations when using union types that you should be aware of:**

* An interface cannot extend a union type:
    

```typescript
type SampleUnionType = string | number;

// The code below will not work
interface extends SampleUnionType { ... }
```

* A class cannot implement a union type:
    

```typescript
type SampleUnionType = string | number;

// The code below will not work
class SampleClass implements SampleUnionType { ... }
```

*A class can implement an interface or type alias, both in the same way. However, it can not implement a type alias that names a union type.*

### Tuples

A tuple is a type that allows you to specify a fixed-length array of values where each element has a specific data type. Here is an example of how to create a type for an array with only two elements:

```typescript
type PersonTuple = [string, number];

const person: PersonTuple = ["John Doe", 25];
```

Even though this can be achieved using interfaces as shown below, you will lose access to all of the array methods. If you try to call `person.length` on the variable created from the interface, you will get the following error: Property 'length' does not exist on type 'PersonTuple'.

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ksgn585yaadoixtf11zn.jpg)

You will have to manually add those methods (length, push, concat, etc.) to the interface as shown below. However, this is not something you want to do. If you need a tuple, consider using a type alias.

```typescript
// How to mimic array methods
interface PersonTuple
{
    0: string;
    1: number;
    length: 2;
}

const person: PersonTuple = ["John Doe", 25];

console.log(person.length); // This will now work
```

### Mapped Types

Mapped types allow you to transform an existing type into a new type by applying a mapping operation to each property of the original type.

```typescript
type NewType = {
  [Property in OldType]: MappingOperation;
}
```

Here, `OldType` is the original type that you want to transform, and `Property` represents each property in `OldType`. `MappingOperation` is a TypeScript type operator that defines how each property in `OldType` will be transformed.

In the example below we create a new type `B`, which has all the properties of `A`, but with each property made optional.

```typescript
type B = {
  [Property in keyof A]?: A[Property];
}
```

*TypeScript does not currently support typing mapped types with interfaces.*

## Difference #3: Declaration Merging

If you have two interfaces that you define with the same name in the same scope, they will be merged. Consider this example:

```typescript
// Declaring SampleType interface for the 1st time
interface SampleType {
  a: number;
  b: number;
};

// Declaring SampleType interface for the 2nd time
interface SampleType {
  c: number;
  d: number;
};

// The second interface declaration extends the first one by adding
// two new properties. Now SampleType has four properties: a, b, c, d
const sampleType: SampleType = {
  a: 1,
  b: 2,
  c: 3,
  d: 4,
};
```

We cannot do the same with types. This is important to consider if you are the author of a library and want your users to be able to extend its functionality by merging interfaces. It will allow them to combine their own type declarations with those provided by the library, effectively "extending" or "augmenting" the library's API.

## Difference #4: Extention

Interfaces can extend other interfaces using the `extends` keyword which allows for greater flexibility and modularity:

```typescript
interface Named {
  name: string;
}

interface Ageable {
  age: number;
}

interface Person extends Named, Ageable {
  sayHello(): void;
}
```

Types can also be extended using an intersection type. An intersection type combines multiple types into one. Consider this example:

```typescript
// Example #1
type A = { a: number };
type B = { b: number };
type C = A & B;

const c: C = { a: 10, b: 20 };

// Example #2
type A = { a: number };
type B = A & { b: number };

const b: B = { a: 10, b: 20 };
```

As you can see, the `&` operator is used to create a new type by combining multiple existing types. The new type has all properties of the existing types.

---

We can also mix them together as shown below. Interfaces and type aliases are not mutually exclusive. An interface can extend a type alias and vice versa.

* Interface extends another interface:
    

```typescript
interface A { sampleProperty: number; }
interface B extends A { sampleProperty: number; }
```

* Interface extends a type alias:
    

```typescript
type A = { sampleProperty: number; }
interface B extends A { sampleProperty: number; }
```

* Type alias extends another type alias:
    

```typescript
type A = { sampleProperty: number; };
type B = A & { sampleProperty: number; };
```

* Type alias extends interface:
    

```typescript
interface A { sampleProperty: number; }
type B = A & { sampleProperty: number; };
```

There are some limitations to what can be extended with interfaces. For example, primitive types, union types, classes, and enums, cannot be extended with interfaces.

## What Should I Use?

**In general, it is recommended to use interfaces for defining object shapes, and types for defining other types of values. However, it is up to you and your team to decide which option to use as long as you are consistent.**

For example, every object should be typed as an interface and everything else as a type. Or you can use interfaces or types for everything, but not both for values of the same type (e.g. types and interfaces for objects). Communication with your team and consistency are crucial for quality code.

Here is a good cheat sheet that I often refer to, however, it may differ for everyone:

When to use `type`:

* Use `type` when defining primitives
    
* Use `type` when defining unions
    
* Use `type` when defining tuples
    
* Use `type` when defining functions
    
* Use `type` when defining mapped types
    

When to use `interface`:

* Use `interface` for all object types where using `type` is not required
    
* Use `interface` when you want to take advantage of declaration merging
    

## Keep an Eye on the Changelog

The limitations and differences described in this article are current as of February 2023. However, with new versions of TypeScript, they can change. It is important to keep an eye on the [release notes](https://devblogs.microsoft.com/typescript/) to stay informed about new changes and features.
    

---

The end, I hope this information was helpful, stay tuned for more content :)

---

## Source

1. [PYPL PopularitY of Programming Language](https://pypl.github.io/PYPL.html)
    
2. [Interfaces vs Types in TypeScript - Stack Overflow](https://stackoverflow.com/questions/37233735/interfaces-vs-types-in-typescript/52682220)
    
3. [TypeScript: Documentation - Everyday Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html)
    
4. [TypeScript: Documentation - Mapped Types](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html)