Les TypeScript Decorators (décorateurs TypeScript) permettent d’ajouter des fonctions supplémentaires à des objets, et ce sans devoir modifier le code source. Ils peuvent être appliqués aux classes, aux méthodes, aux propriétés, aux fonctions d’accès et aux paramètres, et accèdent aux annotations et métadonnées.

Les TypeScript Decorators : c’est quoi et à quoi ça sert ?

Le principe des TypeScript Decorators n’a fondamentalement rien de nouveau. On trouve des concepts similaires dans d’autres langages de programmation comme les attributs en C#, les décorateurs en Python ou les annotations en Java. Il s’agit de pouvoir étendre les fonctions d’un objet sans en modifier le code source. TypeScript aussi travaille depuis longtemps selon cette approche. Certes, la plupart des navigateurs ne supportent pas (encore) les TypeScript Decorators, mais il est tout de même intéressant d’essayer cette méthode et ses possibilités. Depuis la version TypeScript 5.0, leur utilisation a été considérablement simplifiée.

Les TypeScript Decorators sont utilisés pour ajouter des annotations et des métadonnées supplémentaires aux classes TypeScript et aux éléments. Outre les classes, il est possible de modifier les méthodes, les propriétés, les méthodes d’accès ainsi que les paramètres. Ces derniers peuvent être contrôlés et leurs valeurs consultées. Il s’agit de l’une des grandes différences entre les TypeScript Decorators et leur équivalent pour JavaScript.

Managed Nextcloud de IONOS Cloud
Travaillez en équipe dans votre propre Cloud
  • Sécurité des données
  • Outils de collaboration intégrés
  • Hébergement dans des data centers européens

Syntaxe et fonctionnement des décorateurs

En ajoutant des TypeScript Decorators à un objet, vous appelez une fonction qui peut être exécutée sans modification du code source. Vous augmentez ainsi la fonctionnalité tout en gardant un code clair. La syntaxe de base est la suivante :

@nomDuDecorateur
typescript

Vous pouvez créer cette fonction avec deux ou trois paramètres. La syntaxe de la fonction à trois paramètres prend la forme suivante :

function decoratorFonction(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    console.log(`Decorating ${propertyKey} of class ${target.constructor.name}`);
}
class MyClass {
    @decoratorFonction
    myMethod() {
    }
}
typescript

Les différents éléments des TypeScript Decorators sont les suivants :

  • target : désigne l’objet auquel le décorateur a été attribué
  • propertyKey : est un string contenant le nom de la classe à laquelle un décorateur a été attribué ; il peut s’agir, entre autres, de méthodes ou de propriétés
  • descriptor : permet de stocker des informations supplémentaires sur l’objet sur lequel le décorateur est appliqué ; les propriétés possibles sont value, writable, enumerable ou configurable.

Voici, ci-dessous, la syntaxe des TypeScript Decorators a deux paramètres :

function decoratorFonction(target: any) {
    console.log(`Decorating ${target.name}`);
}
@decoratorFonction
class MyClass {
}
typescript

Dans ce cas, les TypeScript Decorators ont été appliqués à une classe.

Les différents types de décorateurs

Il existe différents types de TypeScript Decorators. Nous les présentons plus en détail ci-après, avec leurs particularités respectives :

  • Class Decorators
  • Method Decorators
  • Property Decorators
  • Accessor Decorators
  • Parameter Decorators

TypeScript Decorators pour les classes

Les TypeScript Decorators permettent d’adapter les caractéristiques d’une classe et de modifier son constructeur, ses méthodes ou ses propriétés. Dès que vous « décorez » la classe avec une fonction, vous recevez le constructeur comme premier paramètre. Voici un exemple de code traitant d’une liste de clients. Elle a quelques propriétés privées et publiques :

class Client {
    private static userType: string = "Generic";
    private _email: string;
    public nomduclient: string;
    public rue: string = "";
    public lieuderesidence: string = "";
    public pays: string = "";
    constructor(nomduclient: string, email: string) {
        this.nomduclient = nomduclient;
        this._email = email;
    }
    static get userType() {
        return Client.userType;
    }
    get email() {
        return this._email;
    }
    set email(nouvelemail: string) {
        this._email = nouvelemail;
    }
    adresse(): string {
        return `${this.rue}\n${this.lieuderesidence}\n${this.pays}`;
    }
}
const p = new Client("clientexemple", "name@exemple.com");
p.rue = "6 rue de Drulingen";
p.lieuderesidence = "Strasbourg";
typescript

Dans l’étape suivante, nous utilisons les TypeScript Decorators pour ajouter d’autres fonctions qui ne modifient toutefois pas le code source après coup. Nous ajoutons ainsi le décorateur @frozen pour la classe « Client ». Cette fonction fait en sorte que les objets ne puissent pas être modifiés ultérieurement. Pour certaines propriétés, nous utilisons @required pour indiquer explicitement la saisie. Nous utilisons aussi @enumerable pour les énumérations et @deprecated pour les entrées obsolètes. Voyons tout d’abord ensemble la définition des décorateurs :

function frozen(constructor: Function) {
    Object.freeze(constructor);
    Object.freeze(constructor.prototype);
}
function required(target: any, propertyKey: string) {
}
function enumerable(value: boolean) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        descriptor.enumerable = value;
    };
}
function deprecated(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    console.warn(`The method ${propertyKey} is deprecated.`);
}
typescript

Après l’utilisation des TypeScript Decorators, le code résultant a la syntaxe suivante :

@frozen
class Client {
    private static userType: string = "Generic";
    @required
    private _email: string;
    @required
    public nomduclient: string;
    public rue: string = "";
    public lieuderesidence: string = "";
    public pays: string = "";
    constructor(nomduclient: string, email: string) {
        this. nomduclient = nomduclient;
        this._email = email;
    }
    @enumerable(false)
    static get userType() {
        return Client.userType;
    }
    get email() {
        return this._email;
    }
    set email(nouvelemail: string) {
        this._email = nouvelemail;
    }
    @deprecated
    adresse(): string {
        return `${this.rue}\n${this.lieuderesidence}\n${this.pays}`;
    }
}
const p = new Client("clientexemple", "nom@exemple.com");
p.rue = "6 rue de Drulingen";
p.lieuderesidence = "Strasbourg";
typescript

TypeScript Decorators pour les méthodes

L’utilisation de TypeScript Decorators est également possible pour les méthodes, exception faite des fichiers de déclaration, de l’overloading (surcharge de fonction) ou de la classe « Declare ». Dans l’exemple suivant, nous utilisons @enumerable comme décorateur pour la méthode getName dans la classe « Personne » :

const enumerable = (value: boolean) => {
    return (target: any, propertyKey: string, propertyDescriptor: PropertyDescriptor) => {
        propertyDescriptor.enumerable = value;
    }
}
class Personne {
    prenom: string = "Julie"
    nom: string = "Rault"
    @enumerable(true)
    getName () {
        return `${this.prenom} ${this.nom}`;
    }
}
typescript

TypeScript Decorators pour les propriétés

Les TypeScript Decorators pour les propriétés d’une classe (Property Decorators) ont deux paramètres : la fonction de constructeur de la classe et le nom de la propriété. Dans l’exemple suivant, nous utilisons le décorateur pour afficher le nom d’une propriété (ici le nom du client) :

const printPropertyName = (target: any, propertyName: string) => {
    console.log(propertyName);
};
class Client {
    @printPropertyName
    name: string = "Julie";
}
typescript

TypeScript Decorators pour les fonctions d’accès

Les Accessor Decorators fonctionnent selon un principe très similaire à celui des Property Decorators. À la différence de ces derniers, ils ont un troisième paramètre en plus. Dans notre exemple, il s’agit du Property Descriptor pour un client. En indiquant une valeur avec l’Accessor Decorator, celui-ci devient le nouveau Property Descriptor. Dans le code suivant, la valeur booléenne (« True » ou « False ») de enumerable est ainsi modifiée.

const enumerable = (value: boolean) => {
    return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
        descriptor.enumerable = value;
    }
}
typescript

Voici comment appliquer le décorateur :

class Client {
    prenom: string = "Julie";
    nom: string = "Rault";
    @enumerable(true)
    get name() {
        return `${this.prenom} ${this.nom}`;
    }
}
typescript

TypeScript Decorators pour les paramètres

Les TypeScript Decorators de type Parameter Decorator disposent également de trois paramètres : la fonction de constructeur de classe, le nom de la méthode et en plus une désignation d’index du paramètre. Toutefois, le paramètre en soi ne peut pas être modifié, de sorte que ce décorateur peut être utilisé uniquement pour la vérification. Si vous souhaitez, par exemple, consulter l’index, faites-le avec ce code :

function print(target: Object, propertyKey: string, parameterIndex: number) {
    console.log(`Decorating param ${parameterIndex} from ${propertyKey}`);
}
typescript

Si vous appliquez ensuite le paramètre Décorateur, le code est le suivant :

class Exemple {
    testMethod(param0: any, @print param1: any) {}
}
typescript
Conseil

Idéal pour les sites Internet statiques et les applications : avec Deploy Now de IONOS, vous bénéficiez d’un environnement de simulation (staging) simple, d’une installation rapide et de workflows parfaitement harmonisés. Trouvez le modèle le mieux adapté à vos besoins !

Cet article vous a-t-il été utile ?
Aller au menu principal