
Le match #2 : Types Aliases vs Interfaces en Typescript
Jour de match !
Quelle est la différence entre les Types Aliases et les Interfaces ? Pourquoi utiliser plutôt l’un que l’autre ?
Pour cette deuxième journée, l’affrontement s’annonce une nouvelle fois palpitant. Mais avant de les confronter, on va d’abord en apprendre un peu plus sur chacun d’eux.
Type Aliases en Typescript
Les Types Aliases sont tout simplement des noms donnés à des types. Et comme un exemple vaut mieux qu’un long discours, voici comment on déclare un Type Alias :
type Car = {
brandName: string
model: string
}
On peut aussi utiliser un Type Aliases pour un Union Type ou un type primitif :
type UnionAlias = Car | Bus
type PrimitiveAlias = string
Il est important de noter qu’un Type Alias n’est pas un nouveau type au même titre que les types primitifs qu’on retrouve dans de nombreux langages : string
, boolean
, number
… mais simplement un nom associé à un type, un alias donc !
Interface en Typescript
Les interfaces sont une solution alternative au Type Aliases pour nommer un type d’objet. On les déclare tel que :
interface Car {
brandName: string
model: string
}
Mais alors, pourquoi ces 2 concepts co-existent ? Et bien, car ils ont quelques différences !
Entrons tout de suite dans le vif du sujet !
Étendre
Interfaces
Il est facile d’étendre une interface pour, par exemple, créer des templates d’objet qui nous rappellent les concepts basiques de Programmation Orientée Objet :
interface Animal {
name: string
}
interface Cat extends Animal {
paws: number
}
const maineCoon: Cat = {
name: 'Pepper',
paws: 4,
}
Type Aliases
Pour les types aliases, la syntaxe est un peu différente, mais le résultat est le même.
type Animal = {
name: string
}
type Cat = Animal & {
paws: number
}
const maineCoon: Cat = {
name: 'Pepper',
paws: 4,
}
Égalité, 0️⃣ points !
TIPS : Il est possible d’étendre une interface avec un type et inversement tel que :
type Type1 = {}
interface Interface1 extends Type1 {}
interface Interface2 {}
type Type2 = Type1 & Interface2 {}
Ajouter une propriété
Interfaces
On peut ajouter des propriétés à une interface en redéclarant son nom et les nouvelles propriétés.
interface Vehicle {
name: string
}
interface Vehicle {
model: string
}
Notre interface Vehicle
contient maintenant 2 propriétés : name
et model
/!\ Il est important de noter que cette manière d'ajouter des propriétés à un objet ne doit pas être utilisée n'importe comment, au risque de créer du code illisible et non maintenable si on ne retrouve pas toutes les propriétés au même endroit. Cette logique est intéressante si l'on souhaite, par exemple, étendre une interface d'une librairie externe dans un projet avancé.
Type Aliases
Avec les Types Aliases, ce n’est pas possible.
type Vehicle = {
name: string
}
type Vehicle = {
//Génère l'erreur : Error: Duplicate identifier 'Vehicle'
type: string
}
Pour ajouter une propriété, on est obligé de déclarer un nouvel Alias.
2️⃣ point pour les Interfaces !
Généricité
La Généricité est un concept incontournable de Typescript. Il a donc naturellement été implémenté dans les 2 concepts que nous mettons en face à face. Son objectif est de rendre des propriétés d’un type ou d’une interface variable lors de sa déclaration.
Type Aliases
interface Vehicle<P> {
brand: P
}
const Renault: Vehicle<string> = {
brand: 'renault',
}
Interfaces
type Vehicle<P> = {
brand: P
}
const Renault: Vehicle<string> = {
brand: 'renault',
}
On remarque que les syntaxes des 2 méthodes sont très similaires.
Égalité, 0️⃣ points !
—
Tuples
Types Aliases
Le fonctionnement des Tuples est un concept intéressant en Typescript qui permet de déclarer un set de valeur avec des types différents. On peut l’utiliser avec des types :
type Cat: [string, number] = ['Pepper', 4]
Interfaces
C’est un peu plus complexe avec les interfaces et moins adapté :
interface Cat {
values: [string, number]
}
1️⃣ point pour les types aliases !
—
Renommer un type primitif
Type Aliases
Les Types aliases nous permettent de redéfinir le nom d’un type primitif.
Par exemple, on peut faire :
type PinCode = number
const pinCode: PinCode = 1234
Cela peut permettre de rendre le code plus compréhensible dans certaines situations.
Interfaces
Ce n’est pas vraiment possible avec les interfaces. On pourrait, au mieux, faire :
interface PinCode {
value: number
}
const pinCode: PinCode = { value: 1234 }
1️⃣ point pour les Types Aliases !
—
Performances
Du côté de la performance, nos 2 challengers réagissent strictement de la même manière à la compilation.
Voici notre fichier Typescript :
interface Dog {
name: string
}
type Cat = {
name: string
}
const cat: Cat = { name: 'pepper' }
const dog: Dog = { name: 'scoubidou' }
après transpilation :
var cat = { name: 'pepper' }
var dog = { name: 'scoubidou' }
Les Types Aliases et les interfaces de Typescript sont utilisés uniquement dans la phase de développement et disparaissent lors de la phase de transpilation en Javascript.
Il n’y a donc pas de différence de performance entre ces 2 outils.
Encore une égalité, quel match !
—
Bonus – Interfaces TypeScript et Concept POO
Interfaces
Concept de POO
Comme nous l’avons vu plus haut, les interfaces nous permettent de retrouver le concept d’héritage des classes de la Programmation Orientée Objet avec extends
tels que :
interface Animal {...}
interface Dog extends Animal {...}
On retrouve dans l’interface Dog
toutes les propriétés de l’interface Animal
C’est encore un match serré auquel nous avons eu à faire !
Voici le résumé du match
Types | Interfaces | |
Étendre | 0️⃣ | 0️⃣ |
Ajouter une propriété | 0️⃣ | 2️⃣ |
Généricité | 0️⃣ | 0️⃣ |
Tuples | 1️⃣ | 0️⃣ |
Renommer un type primitif | 1️⃣ | 0️⃣ |
Performances | 0️⃣ | 0️⃣ |
Malgré des différences entre les deux concepts, on retrouve énormément de points communs et de comportements similaires.
Si on se réfère à la documentation officielle de Typescript, celle-ci nous dit que l’on peut utiliser les interfaces par défaut, sauf si celles-ci ne nous permettent pas de répondre à nos besoins.
Mon avis
De mon côté, j’ai choisi de suivre le conseil d’utilisation de la documentation officielle car… c’est la doc officielle 😉
J’utilise, en conséquence, très largement les interfaces !
Alors, plutôt Interfaces ou Type Aliases ?