Type vs. Interface is one of the most confusing and interesting things in TypeScript. We will try to clear up that confusion.

TypeScript is created on top of JavaScript, which adds static types. Having types is a wonderful thing for developers. Writing types will be hard, but you won’t regret it in the long run.

TypeScript has all basic types like number, string, boolean, etc. Along with the basic type, TypeScript allows us to create custom types and define how an object looks with the help of Type Aliases and Interfaces, respectively.

A Type Alias is nothing but a Type. Creating a type with a custom name (alias) makes it a Type Alias, nothing more than that.

Let’s look at the basic syntax of Interfaces and Type Aliases.

Basic Syntax

Interfaces

Interfaces will be declared with the interface keyword. Check the syntax of the interfaces below.

interface InterfaceName {
    keyName: typeOfKey
    ...
}

Take a look at the sample example below.

interface Site {
    name: string;
    url: string;
    pagesCount: number;
}

const geekflare: Site = {
    name: 'Geekflare',
    url: 'https://geekflare.com/',
    pagesCount: 25
}

Type Aliases

Type aliases will be declared using the type keyword. Check the syntax of type aliases below.

type TypeName = {
    keyName: typeOfKey;
    ...
}

Take a look at the sample example below.

type Site = {
    name: string;
    url: string;
    pagesCount: number
}

const geekflare: Site = {
    name: 'Geekflare',
    url: 'https://geekflare.com/',
    pagesCount: 25
}

We have created a type for the Site using the interface and type alias. Both are valid and can be used for the object types mentioned in the examples. Only the syntax is different in the above example, which is obvious.

Let’s continue exploring the differences between them to find more things.

Tuples

A tuple in TypeScript is a typed pre-defined length array. It defines the types of each index.

We can declare tuples using type aliases. But we can’t do it using interfaces. Let’s see how to do it with type aliases.

type Site = [string, string, number]

const geekflare: Site = ['Geekflare', 'https://geekflare.com/', 25]

In the above example, we have defined the type for each index element for the array. If we give some other type in the array, TypeScript will throw an error.

Can’t we do it with interfaces?

We can’t do it exactly as we do it with type aliases. Interfaces are used for object types. So, we need to have the tuple inside the object to use it in interfaces. Let’s see an example.

interface Site {
    details: [string, string];
    pagesCount: number;
}

const geekflare: Site = {
    details: ['Geekflare', 'https://geekflare.com/'],
    pagesCount: 25,
}

If you see the code, we have a tuple called details inside the Interface. So, we can use the tuples inside the interfaces.

Similarly, we can use type aliases for single types like string, number, boolean, etc. As the Interface is used for the object types, we can use it for the single types like type aliases.

Another interesting thing is that we can use the type alias tuple in the interfaces. Check the below example.

type Details = [string, string]

interface Site {
    details: Details;
    pagesCount: number;
}

const geekflare: Site = {
    details: ['Geekflare', 'https://geekflare.com/'],
    pagesCount: 25,
}

Let’s get on to the next thing.

Declaration Merging – Interfaces

Declaration merging is use TypeScript to merge types of interfaces with the same name. Let’s see the example to get more clarity on it.

interface Site {
    name: string;
}

interface Site {
    url: string;
}

interface Site {
    pagesCount: number;
}

const geekflare: Site = {
    name: 'Geeflare',
    url: 'https://geekflare.com/',
    pagesCount: 25,
}

If you see the above code, we have declared the Interface with the same name 3 times. TypeScript compiler will compile all those 3 forms into a single object type which includes all the types from the interfaces which have the same name.

You can confirm the declaration merging by removing one key from the geekflare object. If you remove one of the keys from geekflare, you will see an error.

We can’t do the same thing with type aliases. Most people don’t use that feature. In general, having multiple interfaces with the same name is confusing.

Type alias fans, don’t worry about this feature of interfaces 😅.

Extends

Let’s say you have declared a type. Now, you want to declare another type along with the types of the previous type. In that case, we can extend the previous type. We can do it with both interfaces and type aliases.

Let’s see them both.

Interfaces

There is a keyword called extends for this use case in TypeScript. We will use it to extend the interfaces. Let’s check the example.

interface Site {
    name: string;
    url: string;
    pagesCount: number;
}

interface Geekflare extends Site {
    founder: string;
}

const geekflare: Geekflare = {
    name: 'Geekflare',
    url: 'http://geekflare.com/',
    pagesCount: 25,
    founder: 'Chandan'
}

We have created Geekflare Interface by extending the Site Interface. All the types of Site will be present in Geeflare Interface along with their own types. You can remove name key from the geekflare variable to confirm it.

We can extend multiple interfaces as follows.

interface FirstHalf {
    name: string;
}

interface SecondHalf {
    age: number
}

interface Person extends FirstHalf, SecondHalf {
    profession: string
}

const person: Person = {
    name: 'Geekflare',
    age: 7,
    profession: 'Helping Techies'
} 

Try extending with more than 2 interfaces for fun. We can also extend type aliases with the Interface.

type Site = {
    name: string;
    url: string;
    pagesCount: number;
}

interface Geekflare extends Site {
    founder: string;
}

const geekflare: Geekflare = {
    name: 'Geekflare',
    url: 'http://geekflare.com/',
    pagesCount: 25,
    founder: 'Chandan'
}

We have extended only one type in the above example. You can extend as many as you want, similar to the previous example of extending multiple interfaces.

Let’s see how to do it with type aliases.

Type Aliases

We can extend the type aliases using the intersection type in TypeScript. Let’s see an example.

type Site = {
    name: string;
    url: string;
    pagesCount: number;
}

type Geekflare = Site & {
    founder: string;
}

const geekflare: Geekflare = {
    name: 'Geekflare',
    url: 'http://geekflare.com/',
    pagesCount: 25,
    founder: 'Chandan'
}

We have extended the Site type with founder for Geekflare type using the intersection (&). You can test it by removing one of the keys from the geekflare variable, which will throw an error.

Similar to interfaces, we can extend multiple types as follows.

type FirstHalf = {
    name: string;
}

type SecondHalf = {
    age: number
}

type Person = FirstHalf & SecondHalf & {
    profession: string
}

const person: Person = {
    name: 'Geekflare',
    age: 7,
    profession: 'Helping Techies'
} 

We can also extend interfaces with type aliases the same as interfaces extending type aliases. Check the example below.

interface Site {
    name: string;
    url: string;
    pagesCount: number;
}

type Geekflare = Site & {
    founder: string;
}

const geekflare: Geekflare = {
    name: 'Geekflare',
    url: 'http://geekflare.com/',
    pagesCount: 25,
    founder: 'Chandan'
}

Try extending the combination of type aliases and interfaces.

Implementing

This is not a difference between interfaces and type aliases. Just a feature of class to know.

A class can implement both interface and type alias in the same way. Let’s see the examples for both of them.

Interfaces

interface Site {
    name: string;
    url: string;
    pagesCount: number;
}

class Geekflare implements Site {
    name = 'Geekflare'
    url = 'http://geekflare.com/'
    pagesCount = 25

    constructor() {
        console.log(this.name, this.url, this.pagesCount)
    }
}

Type Aliases

type Site = {
    name: string;
    url: string;
    pagesCount: number;
}

class Geekflare implements Site {
    name = 'Geekflare'
    url = 'http://geekflare.com/'
    pagesCount = 25

    constructor() {
        console.log(this.name, this.url, this.pagesCount)
    }
}

Note: one thing to remember is that we can’t implement union (|) or intersection (&) types with classes.

Final Words

As you see in the articles, we can do everything with both type aliases and interfaces. So, we can’t strictly say that one is better than the other. In the end, it’s one’s personal choice to choose one of them. You will develop your style of using them eventually.

Next, you can check out Typescript vs. Javascript.

Happy Coding 🙂