In TypeScript, both an interface and a type Alias can be used to describe a new named type. this article will see what are the differences between them and what are the best use cases for both types and interfaces in TypeScript
1. Declaration merging
In TypeScript, declaration merging happens when the compiler merges two or more interfaces of the same name into only one declaration. and that is possible only with interfaces, if you try to declare two types of the same name, the compiler will throw an error.
Here is an example of declaration merging in TypeScript.
let's imagine we have two interfaces called Car
interface Car {
carName: string ;
};
interface Car {
carNumber: number;
};
const car: Car = {
carName: "ford",
carNumber: 12345
}
In this example, we first declare the Car interface with one property. Then, we declare it another time, with a different property. Finally, the compiler merges both interfaces into one, since they share the same name.
if we change the interface into a type like this
type Car = {
carName: string ;
};
type Car = {
carNumber: number;
};
// this is wrong don't do it
const car: Car = {
carName: "ford",
carNumber: 12345
}
Typescript will throw us an error
Duplicate identifier Car
'Car' is already defined.
Declaration merging does not work with types.
2. Extends
In Typescript, we can easily extend interfaces .this is not possible with types
Interfaces can extend classes which helps a lot in a more object-oriented way of programming.
for example, there is a class called Album and an interface called Song, we can easily extend this class using an interface
class Album {
details = () => {
console.log("show details of the album")
}
};
interface Song extends Album {
songName: string;
}
we can also extend an interface with another interface
for example, an interface called Song can extend interface Singer
interface Singer {
artistName: string;
}
interface Song extends Singer {
songName: string;
}
if we tried to replace interface with type to extend, typescript will throw us an error
type Singer ={
artistName: string;
}
type Song extends Singer ={ // this is wrong don't do it
songName: string;
}
Cannot find name 'extends'.
'Singer' only refers to a type, but is being used as a value here
3. Implements
In typescript, Both a type and an interface can be implemented by a class, and we can also create classes implementing interfaces.
interface ClockInterface {
currentTime: Date;
}
class Clock implements ClockInterface {
currentTime: Date = new Date();
constructor(h: number, m: number) {}
}
You can also describe methods in an interface that are implemented in the class, as we do with setTime
in the below example:
interface ClockInterface {
currentTime: Date;
setTime(d: Date): void;
}
class Clock implements ClockInterface {
currentTime: Date = new Date();
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) {}
}
a class can also implement a type
type ClockInterface = {
currentTime: Date;
}
class Clock implements ClockInterface {
currentTime: Date = new Date();
constructor(h: number, m: number) {}
}
4. Intersection
Intersection allows the developer to merge two or more type declarations into a single type.
To create an intersection type, we have to use the &
keyword
Here is an example of how to combine two types with an intersection.
type ErrorHandling = {
success: boolean;
error?: { message: string };
}
type ArtworksData = {
artworks: { title: string }[];
}
type ArtworksResponse = ArtworksData & ErrorHandling;
also, we can create a new intersection type combining two interfaces
interface ErrorHandling {
success: boolean;
error?: { message: string };
}
interface ArtistsData {
artists: { name: string }[];
}
type ArtistsResponse = ArtistsData & ErrorHandling;
We cannot create an interface combining two types, because it doesn’t work:
type Name ={
name: "string"
};
type Age ={
age: number
};
interface Person = Name & Age; // this is wrong don't do it
typescript will throw us an error
Parsing error: '{' expected.
'Name' only refers to a type, but is being used as a value here.
'Age' only refers to a type, but is being used as a value here.
5. Tuples
Tuples brought to us this new data type that includes two sets of values of different data types.
type specialKindOfData = [string, number]
it is a very helpful concept in typescript, but we can only declare tuples using types and not interfaces.
but you still are able to use a tuple inside an interface.
for example.
interface Data {
value: [string, number]
}
6. Unions
A union type allows the developer to create a value of one or a few more types.
we have to use the |
keyword to create a new union type, the combined declaration must always be a type
type Cat = {
name: string;
};
type Dog = {
name: string;
};
type Animal = Cat | Dog;
Similar to intersections, we can create a new union type combining two interfaces,
interface Cat {
name: string;
}
interface Dog {
name: string;
}
type Animal = Cat | Dog;
we can not combine two types into an interface because union type must be combined in a type only
7. Primitive Types
A primitive type can only be declared with a type.
type data = string;
If you try to declare one with an interface, it will not work.
Conclusion
In this article, we learned about the difference between Interfaces and types, and learned the best use cases for both types and interfaces in TypeScript, and how we can apply both of them in real projects. .to decide if you should use a type or an interface, you should carefully think and analyze what you’re working on, and the specific code to make the right choice. the interface works better with objects and method objects, and types are better to work with functions, and complex types, you can use both together and they will work fine.
Top comments (2)
is basically the same for
interface ... extends
.But is a song a singer indeed ?
Thanks for sharing!