Type and Type alias

A type is used how our data will look (e.g. number, string, Array, etc.). A type alias gives us a way of assigning names that we choose for types that already exist. Type aliases use the keyword type. They refer to any TypeScript valid type, include types that are primitive (e.g. number, string, boolean, etc.).

type Name = string;

Interfaces

Interfaces on the other hand, allows us to enforce the shape of the data. For example:

interface Item {
  id: number;
  name: string;
  description: string;
  sku: string;
}

What is the difference between a type alias and an interface?

The difference between a type alias and an interface is that a type alias can be used to define a type that is primitive (number, string, boolean, etc.) or even combined with another data type, called a union in the same type:

type Name = string; //A type alias
type Response = boolean | null; //A union type

Interfaces cannot be used to alias primitive types. They can only be used for types that are objects.

Both type alias and interfaces can also be used to represent the signature of a function type:

type MultiplyFunc = (num1: number, num2: number) => number;
interface Multiply {
	(num1: number, num2: number): number;
}

Interfaces have an advantage over type aliases with a feature called Declaration Merging. Declaration Merging is where you declare several interfaces with the same name, but different properties. The TypeScript compiler will then merge all of these interfaces into one interface and merge the properties of each of the separate interfaces into one interface.

interface Employee {
	id: number;
}

interface Employee {
	name: string;
}

interface Employee {
	position: string;
}

The merging done by the compiler will produce the following:

interface Employee {
    id: number;
    name: string;
    position: string;
}

Using Extends and Intersection

When using an interface, one can extend a single or multiple interfaces using the keyword extends. All the methods and properties are inherited in the subsequent interface(s):

interface Admin extends Employee {
	isAdmin: boolean;
}

Alias types on the other hand do not use extends but use what is called intersection:

type Admin = Employee & {roles: string[]};

Using interfaces and type aliases with classes

interface Employee {
	id: number;
	name: string;
	position: string;
}

class User implements Employee {
	id: number;
	name: string;
	position: string;
	active: boolean;
}
type Car = {
	make: string;
	model: string;
}

class Vehicle implements Car {
	make: string;
	model: string;
	year: number;
}

When should interfaces or type aliases be used?

Interfaces should be used if you want to use Declaration Merging and object-oriented programming’s inheritance. Type aliases on the other hand give us different types such as: To create a new type based on a primitive type, to combine more than one type using unions, and overloading functions. Additional uses for type aliases can also be used to create generic types, advanced types, mapped types, conditional types and type guards.