Disclaimer

I'm not a TS-Guru™ myself, this is more of what my day-to-day use has lean me towards over the past years.


Differences

The very own TypeScript documentation mentions they're very similar and very much accomplish a same result, but there are subtle differences that can make scratch your head in a few scenarios.

Here is TS Docs: https://www.typescriptlang.org...

Type aliases and interfaces are very similar, and in many cases you can choose between them freely. Almost all features of an interface are available in type, the key distinction is that a type cannot be re-opened to add new properties vs an interface which is always extendable.

- TypeScript docs

Interfaces work for Object representations (exclusively)


Let's say you want to store a phone number, by business rules you need to allow the record to either be a string or multiple strings in a given format. A Type alias can easily represent that logic in a simpler way.

Using Types:

type Phone = string | string[];

const userPhone: Phone = '8882-2232';
const userTwoPhone: Phone = ['2231-0231', '8234-2341'];

Using Interfaces:

// interface Phone = string; // No can't do! 

// You need an object of course!
interface Phone = {
    number: string | string[];
}

const userPhone: Phone = { number: '8882-2232'};
const userTwoPhone: Phone = { number: ['2231-0231', '8234-2341']};

// And now you have to access the values in object notation of course, userPhone.number ...

It's not always useful but Types can rename/alias primitives.

Types aliases do not allow duplicated identifiers


This is an error for Types:

type Phone = string;
type Phone = string[];

Meanwhile Interfaces...

interface Phone {
    number: string
};

interface Phone {
    carrier: string
};

// There will be an error below, as it will ask for the 'carrier' property to be declared
let myPhone: Phone = {
    number: '8823-2398'
};

Explanation for this behavior is something like "Interfaces can be re-opened and new values are just added".

Which is likely not something I'd like in most scenarios.

Interfaces rock too!

There are things I like about Interfaces, don't get me wrong. As usual with all programming-related "it depends" on the context and what you need to do.

I've been writing PHP for a long time, so,  the extends wording maps representations better on my head:

interface Vehicule {
    wheels: number,
    hp: number,
    doors: number
}

interface Bike extends Omit<Vehicule, 'doors'> {}

const myBike: Bike = {
    wheels: 2,
    hp: 500
};