IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

TypeScript 4.3 est disponible et apporte le mot-clé override pour qu'un dev puisse indiquer clairement
S'il avait l'intention d'ajouter une nouvelle méthode ou de remplacer une méthode existante

Le , par Stéphane le calme

192PARTAGES

5  0 
Si vous n'êtes pas encore familiarisé avec TypeScript, c'est un langage qui s'appuie sur JavaScript en ajoutant une syntaxe pour les types statiques. Des outils comme le compilateur TypeScript peuvent simplement effacer la syntaxe TypeScript, vous laissant avec un JavaScript propre et lisible qui fonctionne n'importe où. Alors, qu'est-ce que cette syntaxe ajoute si elle est simplement effacée ? Eh bien, lorsque vous ajoutez des types dans tout votre code, vous rendez vos intentions explicites, et TypeScript peut vérifier le type de votre code pour détecter les erreurs telles que les fautes de frappe, les erreurs de logique, etc. TypeScript utilise également ces types pour alimenter les outils de l'éditeur, vous offrant des fonctionnalités intéressantes telles que la complétion précise de code, le changement de nom et la possibilité de vous rendre directement à une définition.

Types d'écriture séparés sur les propriétés

En JavaScript, il est assez courant pour les API de convertir les valeurs transmises avant de les stocker. Cela arrive souvent aussi avec les getters et les setters. Par exemple, imaginons que nous ayons une classe avec un setter qui convertit toujours une valeur en number avant de l'enregistrer dans un champ privé.

Code TypeScript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Thing { 
    #size = 0; 
  
    get size() { 
        return this.#size; 
    } 
    set size(value) { 
        let num = Number(value); 
  
        // Don't allow NaN and stuff. 
        if (!Number.isFinite(num)) { 
            this.#size = 0; 
            return; 
        } 
  
        this.#size = num; 
    } 
}

Comment taper ce code JavaScript dans TypeScript ? Eh bien, techniquement, nous n'avons rien à faire de spécial ici - TypeScript peut regarder cela sans types explicites et peut comprendre que la size est un nombre.

Le problème est que la size vous permet de lui attribuer plus que de simples number. Nous pourrions contourner ce problème en disant que la size a le type unknown ou any comme dans cet extrait de code:

Code TypeScript : Sélectionner tout
1
2
3
4
5
6
class Thing { 
    // ... 
    get size(): unknown { 
        return this.#size; 
    } 
}

Mais ce n’est pas bon - unknown oblige les personnes qui lisent size à faire une assertion de type, et any ne détecte d’erreur. Microsoft explique alors « si nous voulons vraiment modéliser des API qui convertissent des valeurs, les versions précédentes de TypeScript nous ont obligés à choisir entre être précis (ce qui facilite la lecture des valeurs et écrire plus dur) et être permissif (ce qui facilite l'écriture des valeurs et la lecture plus difficile) ».

C’est pourquoi TypeScript 4.3 vous permet de spécifier des types de lecture et d’écriture dans les propriétés.

Code TypeScript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Thing { 
    #size = 0; 
  
    get size(): number { 
        return this.#size; 
    } 
  
    set size(value: string | number | boolean) { 
        let num = Number(value); 
  
        // Don't allow NaN and stuff. 
        if (!Number.isFinite(num)) { 
            this.#size = 0; 
            return; 
        } 
  
        this.#size = num; 
    } 
}

Dans l'exemple ci-dessus, notre accesseur set prend un ensemble plus large de types (chaînes, booléens et nombres), mais notre accesseur get garantit toujours qu'il s'agira d'un nombre. Maintenant, nous pouvons enfin attribuer d'autres types à ces propriétés sans erreur!

Code TypeScript : Sélectionner tout
1
2
3
4
5
6
7
8
9
let thing = new Thing(); 
  
// Assigning other types to `thing.size` works! 
thing.size = "hello"; 
thing.size = true; 
thing.size = 42; 
  
// Reading `thing.size` always produces a number! 
let mySize: number = thing.size;

Lorsque l'on considère la relation entre deux propriétés portant le même nom, TypeScript n'utilisera que le type « lecture » (par exemple, le type sur l'accesseur get ci-dessus). Les types « écriture » ne sont pris en compte que lors de l'écriture directe dans une propriété.

Gardez à l'esprit qu'il ne s'agit pas d'un modèle limité aux classes. Vous pouvez écrire des getters et des setters avec différents types dans les littéraux d'objet.

Code TypeScript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function makeThing(): Thing { 
    let size = 0; 
    return { 
        get size(): number { 
            return size; 
        }, 
        set size(value: string | number | boolean) { 
            let num = Number(value); 
  
            // Don't allow NaN and stuff. 
            if (!Number.isFinite(num)) { 
                size = 0; 
                return; 
            } 
  
            size = num; 
        } 
    } 
}

En fait, Microsoft a ajouté une syntaxe aux interfaces / types d'objets pour prendre en charge différents types de lecture / écriture sur les propriétés.

Code TypeScript : Sélectionner tout
1
2
3
4
5
// Now valid! 
interface Thing { 
    get size(): number 
    set size(value: number | string | boolean); 
}

L’une des limites de l’utilisation de différents types pour la lecture et l’écriture de propriétés est que le type de lecture d’une propriété doit être attribuable au type que vous écrivez. En d'autres termes, le type getter doit être assignable au setter. Cela garantit un certain niveau de cohérence, de sorte qu'une propriété est toujours attribuable à elle-même.

override et --noImplicitOverride

Lorsque vous étendez des classes en JavaScript, le langage rend très facile le remplacement des méthodes - mais malheureusement, vous pouvez rencontrer des erreurs. Il manque un grand nombre de noms. Par exemple, prenez les classes suivantes:

Code TypeScript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class SomeComponent { 
    show() { 
        // ... 
    } 
    hide() { 
        // ... 
    } 
} 
  
class SpecializedComponent extends SomeComponent { 
    show() { 
        // ... 
    } 
    hide() { 
        // ... 
    } 
}

SpecializedComponent sous-classe SomeComponent et remplace les méthodes show et hide. Que se passe-t-il si quelqu'un décide de supprimer show et hide et de les remplacer par une seule méthode?

Code TypeScript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class SomeComponent { 
-    show() { 
-        // ... 
-    } 
-    hide() { 
-        // ... 
-    } 
+    setVisible(value: boolean) { 
+        // ... 
+    } 
 } 
 class SpecializedComponent extends SomeComponent { 
     show() { 
         // ... 
     } 
     hide() { 
         // ... 
     } 
 }

Notre SpecializedComponent n'a pas été mis à jour. Une partie du problème ici est qu'un utilisateur ne peut pas indiquer clairement s'il avait l'intention d'ajouter une nouvelle méthode ou de remplacer une méthode existante. C’est pourquoi TypeScript 4.3 ajoute le mot-clé override.

Code TypeScript : Sélectionner tout
1
2
3
4
5
6
7
8
class SpecializedComponent extends SomeComponent { 
    override show() { 
        // ... 
    } 
    override hide() { 
        // ... 
    } 
}

Lorsqu'une méthode est marquée par override, TypeScript s'assurera toujours qu'une méthode portant le même nom existe dans une classe de base.

Code TypeScript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class SomeComponent { 
    setVisible(value: boolean) { 
        // ... 
    } 
} 
class SpecializedComponent extends SomeComponent { 
    override show() { 
//  ~~~~~~~~ 
// Error! This method can't be marked with 'override' because it's not declared in 'SomeComponent'. 
        // ... 
    } 
  
    // ... 
}

Il s’agit d’une grande amélioration, mais cela n’aide pas si vous oubliez d’écrire un override sur une méthode - et c’est également une grave erreur que les utilisateurs peuvent rencontrer.

Par exemple, vous pourriez accidentellement « piétiner » une méthode qui existe dans une classe de base sans vous en rendre compte.

Code TypeScript : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
class Base { 
    someHelperMethod() { 
        // ... 
    } 
} 
  
class Derived extends Base { 
    // Oops! We weren't trying to override here, 
    // we just needed to write a local helper method. 
    someHelperMethod() { 
        // ... 
    } 
}

C’est pourquoi TypeScript 4.3 fournit également un nouvel indicateur --noImplicitOverride. Lorsque cette option est activée, il devient une erreur de remplacer toute méthode d'une superclasse à moins que vous n'utilisiez explicitement un mot-clé override. Dans ce dernier exemple, TypeScript ferait une erreur sous --noImplicitOverride, et donnerait un indice indiquant qu'il faut probablement renommer notre méthode à l'intérieur de Derived.

Source : Microsoft

Une erreur dans cette actualité ? Signalez-nous-la !