L’interface est une structure qui définit le contrat dans votre application. Elle définit la syntaxe que les classes doivent suivre. Les classes qui sont dérivées d’une interface doivent suivre la structure fournie par leur interface.
Le compilateur TypeScript ne convertit pas l’interface en JavaScript. Il utilise l’interface pour la vérification de type. Ceci est également connu sous le nom de « typage en canard » ou de « sous-typage structurel ».
Une interface est définie avec le mot clé interface
et elle peut inclure des propriétés et des déclarations de méthodes en utilisant une fonction ou une fonction flèche.
Copie
interface IEmployee { empCode: number; empName: string; getSalary: (number) => number; // arrow function getManagerName(number): string; }
Dans l’exemple ci-dessus, l’interface IEmployee
comprend deux propriétés empCode
et empName
. Elle comprend également une déclaration de méthode getSalaray
utilisant une fonction flèche qui comprend un paramètre numérique et un type de retour numérique. La méthode getManagerName
est déclarée en utilisant une fonction normale. Cela signifie que tout objet de type IEmployee
doit définir les deux propriétés et les deux méthodes.
Interface comme type
L’interface en TypeScript peut être utilisée pour définir un type et aussi pour l’implémenter dans la classe.
L’interface suivante IEmployee
définit le type d’une variable.
Copie
interface KeyPair { key: number; value: string;}let kv1: KeyPair = { key:1, value:"Steve" }; // OKlet kv2: KeyPair = { key:1, val:"Steve" }; // Compiler Error: 'val' doesn't exist in type 'KeyPair'let kv3: KeyPair = { key:1, value:100 }; // Compiler Error:
Dans l’exemple ci-dessus, une interface KeyPair
comprend deux propriétés key
et value
. Une variable kv1
est déclarée comme type KeyPair
. Elle doit donc suivre la même structure que KeyPair
. Cela signifie que seul un objet avec les propriétés key
de type nombre et value
de type chaîne de caractères peut être affecté à une variable kv1
. Le compilateur TypeScript affichera une erreur s’il y a un changement dans le nom des propriétés ou si le type de données est différent de KeyPair
. Une autre variable kv2
est également déclarée de type KeyPair
mais la valeur assignée est val
au lieu de value
, ce qui provoquera une erreur. De la même manière, kv3 attribue un nombre à la propriété value
, donc le compilateur montrera une erreur. Ainsi, TypeScript utilise une interface pour assurer la bonne structure d’un objet.
Interface comme type de fonction
L’interface TypeScript est également utilisée pour définir le type d’une fonction. Cela permet de garantir la signature de la fonction.
Copie
interface KeyValueProcessor{ (key: number, value: string): void;};function addKeyValue(key:number, value:string):void { console.log('addKeyValue: key = ' + key + ', value = ' + value)}function updateKeyValue(key: number, value:string):void { console.log('updateKeyValue: key = '+ key + ', value = ' + value)} let kvp: KeyValueProcessor = addKeyValue;kvp(1, 'Bill'); //Output: addKeyValue: key = 1, value = Bill kvp = updateKeyValue;kvp(2, 'Steve'); //Output: updateKeyValue: key = 2, value = Steve
Dans l’exemple ci-dessus, une interface KeyValueProcessor
comprend une signature de méthode. Celle-ci définit le type de fonction. Maintenant, nous pouvons définir une variable de type KeyValueProcessor
qui ne peut pointer que vers des fonctions ayant la même signature que celle définie dans l’interface KeyValueProcessor
. Ainsi, la fonction addKeyValue
ou updateKeyValue
est assignée à kvp
. Ainsi, kvp
peut être appelée comme une fonction.
Tenter d’assigner une fonction avec une signature différente provoquera une erreur.
function delete(key:number):void { console.log('Key deleted.')} let kvp: KeyValueProcessor = delete; //Compiler Error
Interface pour le type de tableau
Une interface peut également définir le type d’un tableau où vous pouvez définir le type d’index ainsi que les valeurs.
Copie
interface NumList { :number}let numArr: NumList = ;numArr;numArr;interface IStringList { :string}let strArr : IStringList;strArr = "TypeScript";strArr = "JavaScript";
Dans l’exemple ci-dessus, l’interface NumList
définit un type de tableau avec l’index comme nombre et la valeur comme type nombre. De la même manière, IStringList
définit un tableau de chaînes de caractères avec l’index comme chaîne de caractères et la valeur comme chaîne de caractères.
Propriété optionnelle
Parfois, nous pouvons déclarer une interface avec un excès de propriétés mais nous ne nous attendons pas à ce que tous les objets définissent toutes les propriétés données de l’interface. Nous pouvons avoir des propriétés optionnelles, marquées par un » ? ». Dans ce cas, les objets de l’interface peuvent ou non définir ces propriétés.
Copie
interface IEmployee { empCode: number; empName: string; empDept?:string;}let empObj1:IEmployee = { // OK empCode:1, empName:"Steve"}let empObj2:IEmployee = { // OK empCode:1, empName:"Bill", empDept:"IT"}
Dans l’exemple ci-dessus, empDept
est marqué avec ?
, donc les objets de IEmployee
peuvent ou non inclure cette propriété.
Propriétés en lecture seule
TypeScript fournit un moyen de marquer une propriété comme étant en lecture seule. Cela signifie qu’une fois qu’une valeur est attribuée à une propriété, elle ne peut pas être modifiée!
Copie
interface Citizen { name: string; readonly SSN: number;}let personObj: Citizen = { SSN: 110555444, name: 'James Bond' }personObj.name = 'Steve Smith'; // OKpersonObj.SSN = '333666888'; // Compiler Error
Dans l’exemple ci-dessus, la propriété SSN
est en lecture seule. Nous définissons l’objet personObj de type Citizen et attribuons des valeurs aux deux propriétés de l’interface. Ensuite, nous essayons de modifier les valeurs attribuées aux deux propriétés –name
et SSN
. Le compilateur TypeScript affiche une erreur lorsque nous essayons de modifier la propriété SSN
en lecture seule.
Extension des interfaces
Les interfaces peuvent étendre une ou plusieurs interfaces. Cela rend l’écriture des interfaces flexible et réutilisable.
Copie
interface IPerson { name: string; gender: string;}interface IEmployee extends IPerson { empCode: number;}let empObj:IEmployee = { empCode:1, name:"Bill", gender:"Male"}
Dans l’exemple ci-dessus, l’interface IEmployee
étend l’interface IPerson
. Ainsi, les objets de IEmployee
doivent inclure toutes les propriétés et méthodes de l’interface IPerson
sinon, le compilateur affichera une erreur.
Implémentation d’une interface
Similairement à des langages comme Java et C#, les interfaces en TypeScript peuvent être implémentées avec une classe. La classe implémentant l’interface doit se conformer strictement à la structure de l’interface.
Copie
interface IEmployee { empCode: number; name: string; getSalary:(number)=>number;}class Employee implements IEmployee { empCode: number; name: string; constructor(code: number, name: string) { this.empCode = code; this.name = name; } getSalary(empCode:number):number { return 20000; }}let emp = new Employee(1, "Steve");
Dans l’exemple ci-dessus, l’interface IEmployee
est mise en œuvre dans la classe Employé en utilisant le mot-clé implement. La classe d’implémentation doit strictement définir les propriétés et la fonction avec le même nom et le même type de données. Si la classe d’implémentation ne suit pas la structure, alors le compilateur montrera une erreur.
Bien sûr, la classe d’implémentation peut définir des propriétés et des méthodes supplémentaires, mais elle doit au moins définir tous les membres d’une interface.
Dans le prochain chapitre, nous en apprendrons davantage sur les classes TypeScript.