What is the difference between type vs interface in Typescript
Tags: typescript, webdev, keyword, difference
Published: 2024-06-08 05:25:35

## Common
Both can define a data type.
Types aliases in Typescript mean "a new for any type".

```typescript
type MyNumber = number;

type StringOrNumber = string | number;

type User = {
  id: number;
  name: string;
  email: string;
}
```
An interface defines a contract that an object must adhere to.
```typescript
interface Person { 
  name: string; 
  address: string;
}
```

## Difference
### 1. Primitive Type
Primitive types are inbuilt types in TypeScripts. They include number, string, boolean, null, and undefined types.
Type alias can be used to define a alias for a primitive type as below.
```typescript
type MyString = string;
type NullOrUndefined = null | undefined;
```
But, interface can not be used to define a alias for a primitive type.
### 2. Union types
Union types can describe values that can be one of several constant and create unions of various primitive, literal or complex types.
```typescript
type Computer = 'Desktop' | 'Laptop' | 'Tablet';
```
Union type can only be defined using type. Interface cannot define a union type. But it is possible to create a new union type from several interfaces:
```typescript
interface Laptop {
  cpu: string;
  ram: number;
  storage: number;
}

interface SmartPhone {
  number: string;
}

type Mobile = Laptop | Phone;
```
## 3. Function types
In Typescript, a function type represents a function's prototype. Type alias defines function prototype like this:
```typescript
type Add = (num1: number, num2: number) => number;
```
You can also use an interface to do samething:
```typescript
interface IAdd {
  (num: number, num2: number): number;
}
```
As you can see both type and interface are similar except for a syntax difference. And type is preferred to define a function prototype.
It is also because type has more capability to define function type. Here's an example:
```typescript
type Watch = 'Mechanical' | 'Electrical';

type WindUp = (cycle: number) => void;
type Recharge = () => void;

type RefillWatch<W extends Watch> = 
  W extends 'Mechanical' ? 
  WindUp : W extends 'Electrical' ? 
    Recharge : never;

const windUp: RefillWatch<'Mechanical'> = (watch, cycle) => {
  // Something to wind up the spring of the watch
}

const recharge: RefillWatch<'Electrical'> = (watch) => {
  // Something to charge the watch
}
```
## 4. Merging of declarations
Merging of declarations is a feature for only interface.
```typescript
interface Computer {
  cpu: string;
}
interface Computer {
  ram: string;
}

const mine: Computer = {
  cpu: 'Core i-9 9900',
  ram: '32GB',
};
```
## 5. Extends and intersection
An interface can extend original interface:
```typescript
interface Computer {
  cpu: string;
  ram: string;
}

interface Laptop extends Computer {
  battery: string;
}
```
You can also get same result with type alias:
```typescript
type Computer = {
  cpu: string;
  ram: string;
}

type Laptop = Computer & {
  battery: string;
}
```
You can also extends an interface from a type alias:
```typescript
type Computer = {
  cpu: string;
  ram: string;
}
interface Laptop extends Computer {
  battery: string;
}
```
But you cannot extend an interface from a union type:
```typescript
type Watch = 'Mechanical' | 'Electrical';
interface MoreWatch extends Watch {
  brand: string;
}
```
Type aliases can extend interfaces using the intersection like this:
```typescript
interface Watch {
  brand: string;
}
Type ElectricWatch = Watch & {
  battery: string;
}
```
## 6. Handling conflicts
You cannot extend an interface with same property key like this:
```typescript
interface Watch {
  refill: () => void;
}
interface Watch {
  refill: (cycle: number) => void;
}
```
But you can extend a type alias with same property key like this:
```typescript
type Person = {
  getPermission: (id: string) => string;
};
type Staff = Person & {
   getPermission: (id: string[]) => string[];
};
const AdminStaff: Staff = {
  getPermission: (id: string | string[]) => {
    return (typeof id === 'string' ? 
      'admin' : ['admin']) as string[] & string;
  }
}
```
If you extend a type alias like this, the model property type would not be determined because it can't be both string and number at the same time:
```typescript
type Computer = {
  model: string;
};
type Laptop = Computer & {
  model: number;
};
// error: Type 'string' is not assignable to type 'never'.(2322)
const mine: Laptop = { model: 'Dell' };
```
## 7. Implementing class
In Typescript, you can implement a class using either an interface or a type alias:
```typescript
interface Person {
  name: string;
  greet(): void;
}
class Student implements Person {
  name: string;
  greet() {
    console.log('Hello');
  }
}
type Pet = {
  name: string;
  greet(): void;
};
class Cat implements Pet {
  name: string;
  greet() {
    console.log('Mew');
  }
}
```
But you cannot implement a class that extends a union type:
```typescript
type Key = { key: number; } | { key: string; };
// can not implement a union type
class PrimaryKey implements Key {
  key = 1
}
```
## 8. Tuple type
In Typescript, the tuple type can express an array with a fixed number of elements, while each element has its data type:
```typescript
type State: [name: string; setter: (value: string) => void];
```
If you want to declare a tuple type with an interface, you can do it like this:
```typescript
interface IState extends Array<string | (value: string) => void> {
  0: string;
  1: (value: string) => void;
}
```
## 9. Benefits of the type alias than the interface
Here's an example of the advanced type feature that the interface cannot achieve:
```typescript
type Person = {
    name: string;
    address: string;
}
type Getters<T> = {
    [K in keyof T as `get${Capitalize<string & K>}`]:  () => T[K];
};
type PersonType = Getters<Perso>;
// type PersonType = {
//     getName: () => string;
//     getAddress: () => string;
// }
```
## Conclusion
In this post, I have explained the features of the type alias and the interface in Typescript.
As above the type alias has more powerful features than the interface. So I recommend to use the type alias when coding.