Interface vs Type alias
“Interface vs Type” is kind of incorrect. Type refers to the types of TypeScript, like String, Boolean, Number etc.
We can use the type
keyword to define type aliases that comprise of existing types. Take a look at the following example:
type ColorValue = string | number;
type User = {
id: string;
email: string;
}
The type ColorValue
merely refers to a union type between string
and number
.
Interfaces define a contract that an object must adhere to:
interface IUser {
id: string;
email: string;
}
The type User
and the interface IUser
reflects basically the same thing here.
Dealing with the primitive types
One simple yet significant difference is, the type
keyword can deal with primitive type, notice the type ColorValue
. On the other hand, interface must be an object type.
Condition in Types
Types can have conditional values:
type UserType = 'Admin' | 'Normal';
type ViewProfile = (userId: string) => void;
type EditProfile = (userId: string, hasPermisison: boolean) => void;
type UserActions<T extends UserType> = T extends 'Admin'
? EditProfile
: T extends 'Normal'
? ViewProfile
: never;
const adminUserAction: UserActions<'Admin'> = (id, hasPermission) => {
// Implementation for editing user profile (Admin action)
console.log('Editing user profile');
};
const normalUserAction: UserActions<'Normal'> = (id) => {
// Implementation for viewing user profile (Normal action)
console.log('Viewing user profile');
};
Declaration Merging
Interfaces support declaration merging. If you’re using a library that exposes an interface, you can write your own interface with the same name. This will result in merging the interface members. Please note, the property names must be unique!
interface Car {
brand: string;
}
interface Car {
model: string;
}
const car: Car = {
brand: 'Tesla',
model: 'Model 3'
}
Extending an interface and a type
interface Car {
brand: string;
}
interface EV extends Car {
power: number
}
type Car = {
brand: string;
}
type EV = Car & {power: number};
Good to know
You can extend an interface from a type alias with statically known members:
type Car = {
brand: string;
};
interface EV extends Car {
power: number
}
But the following can’t happen, because an interface can only extend an object type. Hence, the following is incorrect:
type Cars = 'EV' | 'ICE';
type Car = 'EV';
interface LatestCar extends Cars {
year: number;
}
interface EVInfo extends Car {
power: number;
}
Type aliases can extend interfaces:
interface Car {
name: string;
}
type EV = Car & { power: number};