Remarque : Cette page est obsolète. La liste complète est disponible sur https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler .
Présentation
Le compilateur Closure peut utiliser des informations sur les types de données des variables JavaScript pour fournir une optimisation et des avertissements améliorés. JavaScript, en revanche, ne permet pas de déclarer des types.
Comme JavaScript ne dispose d'aucune syntaxe pour déclarer le type d'une variable, vous devez utiliser des commentaires dans le code pour spécifier le type de données.
Le langage de typographie du compilateur Closure est dérivé des annotations utilisées par l'outil de génération de documents JSDoc, bien qu'il ait évolué depuis. Il inclut désormais plusieurs annotations que JSDoc ne prend pas en charge, et vice versa. Ce document décrit l'ensemble des annotations et des expressions de type que comprend Closure Compiler.
Balises JSDoc
Le compilateur Closure recherche des informations sur les types dans les balises JSDoc. Utilisez les balises JSDoc décrites dans le tableau de référence ci-dessous pour aider le compilateur à optimiser votre code et à vérifier s'il contient d'éventuelles erreurs de type et autres erreurs.
Ce tableau n'inclut que les tags qui affectent le comportement du compilateur Closure. Pour en savoir plus sur les autres tags JSDoc, consultez la documentation JSDoc Toolkit.
Tag | Description |
---|---|
@abstract
|
Marque une méthode comme abstraite. Comme pour la définition d'une méthode sur
Le compilateur génère un avertissement si une méthode marquée avec /** @abstract */ foo.MyClass.prototype.abstractMethod = function() {}; |
@const
|
Marque une variable comme étant en lecture seule. Le compilateur peut insérer les variables La déclaration de type est facultative.
Le compilateur génère un avertissement si une variable marquée avec /** @const */ var MY_BEER = 'stout'; /** * My namespace's favorite kind of beer. * @const {string} */ mynamespace.MY_BEER = 'stout'; /** @const */ MyClass.MY_BEER = 'stout'; |
@constructor
|
Marque une fonction comme constructeur.
Le compilateur exige une annotation Exemple : /** * A rectangle. * @constructor */ function GM_Rect() { ... } |
@define
|
Indique une constante qui peut être remplacée par le compilateur au moment de la compilation.
Dans l'exemple de gauche, vous pouvez transmettre l'indicateur --define='ENABLE_DEBUG=false' au compilateur pour remplacer la valeur de ENABLE_DEBUG par false.
Le type d'une constante définie peut être un nombre, une chaîne ou une valeur booléenne.
Les définitions ne sont autorisées que dans le champ d'application global.
Exemple : /** @define {boolean} */ var ENABLE_DEBUG = true; /** @define {boolean} */ goog.userAgent.ASSUME_IE = false; |
@deprecated
|
Marque une fonction, une méthode ou une propriété de sorte que son utilisation génère un avertissement du compilateur indiquant qu'elle ne doit plus être utilisée. Exemple : /** * Determines whether a node is a field. * @return {boolean} True if the contents of * the element are editable, but the element * itself is not. * @deprecated Use isField(). */ BN_EditUtil.isTopEditableField = function(node) { ... }; |
@dict
|
Exemple : /** * @constructor * @dict */ function Foo() {} var obj1 = new Foo(); obj1['x'] = 123; obj1.x = 234; // warning var obj2 = /** @dict */ { 'x': 321 }; obj2.x = 123; // warning |
@enum
|
Spécifie le type d'une énumération. Une énumération est un objet dont les propriétés constituent un ensemble de constantes associées. La balise Le libellé de type d'une énumération s'applique à chaque propriété de l'énumération. Par exemple, si une énumération est de type Exemple : /** * Enum for tri-state values. * @enum {number} */ project.TriState = { TRUE: 1, FALSE: -1, MAYBE: 0 }; |
@export
|
Prenons l'exemple de code suivant : /** @export */ foo.MyPublicClass.prototype.myPublicMethod = function() { // ... };
Lorsque le compilateur est exécuté avec l'indicateur goog.exportProperty(foo.MyPublicClass.prototype, 'myPublicMethod', foo.MyPublicClass.prototype.myPublicMethod); qui exportera les symboles vers le code non compilé. Vous pouvez écrire /** * @export * @type {SomeType} */ Le code qui utilise l'annotation
|
@extends
|
Marque une classe ou une interface comme héritant d'une autre classe. Une classe marquée avec
Remarque :
Pour obtenir un exemple d'implémentation de l'héritage, consultez la fonction Exemple : /** * Immutable empty node list. * @constructor * @extends {goog.ds.BasicNodeList} */ goog.ds.EmptyNodeList = function() { ... }; |
@final
|
Indique que cette classe ne peut pas être étendue. Pour les méthodes, indique qu'aucune sous-classe n'est autorisée à remplacer cette méthode. Exemple : /** * A class that cannot be extended. * @final * @constructor */ sloth.MyFinalClass = function() { ... } /** * A method that cannot be overridden. * @final */ sloth.MyFinalClass.prototype.method = function() { ... }; |
@implements
|
Utilisé avec
Le compilateur génère un avertissement si vous marquez un constructeur avec Exemple : /** * A shape. * @interface */ function Shape() {}; Shape.prototype.draw = function() {}; /** * @constructor * @implements {Shape} */ function Square() {}; Square.prototype.draw = function() { ... }; |
@implicitCast
|
Cette annotation ne peut apparaître que dans les déclarations de propriétés externes.
La propriété a un type déclaré, mais vous pouvez lui attribuer n'importe quel type sans avertissement. Lorsque vous accédez à la propriété, vous obtenez une valeur du type déclaré. Par exemple, /** * @type {string} * @implicitCast */ Element.prototype.innerHTML; |
@inheritDoc
|
Indique qu'une méthode ou une propriété d'une sous-classe masque intentionnellement une méthode ou une propriété de la super-classe et possède exactement la même documentation. Notez que la balise Exemple : /** @inheritDoc */ project.SubClass.prototype.toString = function() { ... }; |
@interface
|
Marque une fonction comme interface. Une interface spécifie les membres requis d'un type. Toute classe qui implémente une interface doit implémenter toutes les méthodes et propriétés définies sur le prototype de l'interface. Voir
Le compilateur vérifie que les interfaces ne sont pas instanciées. Si le mot clé Exemple : /** * A shape. * @interface */ function Shape() {}; Shape.prototype.draw = function() {}; /** * A polygon. * @interface * @extends {Shape} */ function Polygon() {}; Polygon.prototype.getSides = function() {}; |
@lends
|
Indique que les clés d'un littéral d'objet doivent être traitées comme des propriétés d'un autre objet. Cette annotation ne doit apparaître que sur les littéraux d'objet.
Notez que le nom entre accolades n'est pas un nom de type comme dans d'autres annotations. Il s'agit d'un nom d'objet. Il nomme l'objet auquel les propriétés sont prêtées.
Par exemple, La documentation de JSDoc Toolkit fournit plus d'informations sur cette annotation. Exemple : goog.object.extend( Button.prototype, /** @lends {Button.prototype} */ ({ isButton: function() { return true; } })); |
@license ou @preserve
|
Indique au compilateur d'insérer le commentaire associé avant le code compilé pour le fichier marqué. Cette annotation permet aux avis importants (tels que les licences légales ou le texte sur les droits d'auteur) de survivre à la compilation sans être modifiés. Les sauts de ligne sont conservés. Exemple : /** * @preserve Copyright 2009 SomeThirdParty. * Here is the full license text and copyright * notice for this file. Note that the notice can span several * lines and is only terminated by the closing star and slash: */ |
@nocollapse
|
Désigne une propriété qui ne doit pas être réduite par le compilateur en une variable. L'utilisation principale de Exemple : /** * A namespace. * @const */ var foo = {}; /** * @nocollapse */ foo.bar = 42; window['foobar'] = foo.bar; |
@nosideeffects
|
Indique qu'un appel à la fonction externe déclarée n'a aucun effet secondaire.
Cette annotation permet au compilateur de supprimer les appels à la fonction si la valeur renvoyée n'est pas utilisée. L'annotation n'est autorisée que dans Exemple : /** @nosideeffects */ function noSideEffectsFn1() {} /** @nosideeffects */ var noSideEffectsFn2 = function() {}; /** @nosideeffects */ a.prototype.noSideEffectsFn3 = function() {}; |
@override
|
Indique qu'une méthode ou une propriété d'une sous-classe masque intentionnellement une méthode ou une propriété de la super-classe. Si aucune autre annotation n'est incluse, la méthode ou la propriété hérite automatiquement des annotations de sa superclasse. Exemple : /** * @return {string} Human-readable representation of * project.SubClass. * @override */ project.SubClass.prototype.toString = function() { ... }; |
@package
|
Marque un membre ou une propriété comme étant privés au niveau du package. Seul le code du même répertoire peut accéder aux noms marqués
Les constructeurs publics peuvent avoir des propriétés Exemple : /** * Returns the window object the foreign document resides in. * * @return {Object} The window object of the peer. * @package */ goog.net.xpc.CrossPageChannel.prototype.getPeerWindowObject = function() { // ... }; |
@param
|
Utilisé avec les définitions de méthodes, de fonctions et de constructeurs pour spécifier les types d'arguments de fonction. Les balises
La balise
Vous pouvez également annoter les types de paramètres en ligne (voir la fonction Exemple : /** * Queries a Baz for items. * @param {number} groupNum Subgroup id to query. * @param {string|number|null} term An itemName, * or itemId, or null to search everything. */ goog.Baz.prototype.query = function(groupNum, term) { ... }; function foo(/** number */ a, /** number */ b) { return a - b + 1; } /** * @param {{name: string, age: number}} person */ function logPerson({name, age}) { console.log(`${name} is ${age} years old`); } |
@private
|
Marque un membre comme privé. Seul le code du même fichier peut accéder aux variables et fonctions globales marquées
Les propriétés statiques publiques des constructeurs marqués Exemple : /** * Handlers that are listening to this logger. * @private {Array<Function>} */ this.handlers_ = []; |
@protected
|
Indique qu'un membre ou une propriété sont protégés.
Une propriété marquée
Exemple : /** * Sets the component's root element to the given element. * Considered protected and final. * @param {Element} element Root element for the component. * @protected */ goog.ui.Component.prototype.setElementInternal = function(element) { // ... }; |
@record
|
Marque une fonction comme interface structurelle. Une interface structurelle est semblable à une interface nominale Exemple : /** * Anything with a draw() method. * @record */ function Drawable() {}; Drawable.prototype.draw = function() {}; /** * A polygon. * @param {!Drawable} x */ function render(x) { x.draw(); }; var o = { draw() { /* ... */ } }; render(o); |
@return
|
Spécifie les types de retour des définitions de méthodes et de fonctions.
La balise
Vous pouvez également annoter le type renvoyé de manière intégrée (voir la fonction
Si une fonction qui ne se trouve pas dans les externs n'a pas de valeur de retour, vous pouvez omettre la balise Exemple : /** * Returns the ID of the last item. * @return {string} The hex ID. */ goog.Baz.prototype.getLastId = function() { ... return id; }; function /** number */ foo(x) { return x - 1; } |
@struct
|
Exemple : /** * @constructor * @struct */ function Foo(x) { this.x = x; } var obj1 = new Foo(123); var someVar = obj1.x; // OK obj1.x = "qwerty"; // OK obj1['x'] = "asdf"; // warning obj1.y = 5; // warning var obj2 = /** @struct */ { x: 321 }; obj2['x'] = 123; // warning |
@template
|
Consultez Types génériques. Exemple : /** * @param {T} t * @constructor * @template T */ Container = function(t) { ... }; |
@this
|
Spécifie le type d'objet auquel le mot clé
Pour éviter les avertissements du compilateur, vous devez utiliser une annotation Exemple : chat.RosterWidget.extern('getRosterElement', /** * Returns the roster widget element. * @this {Widget} * @return {Element} */ function() { return this.getComponent().getElement(); }); |
@throws
|
Utilisé pour documenter les exceptions générées par une fonction. Le vérificateur de type n'utilise pas ces informations pour le moment. Il n'est utilisé que pour déterminer si une fonction déclarée dans un fichier externs a des effets secondaires. Exemple : /** * @throws {DOMException} */ DOMApplicationCache.prototype.swapCache = function() { ... }; |
@type
|
Identifie le type d'une variable, d'une propriété ou d'une expression. La balise Lorsque vous déclarez un paramètre de variable ou de fonction, vous pouvez écrire l'annotation de type en ligne en omettant Exemple : /** * The message hex ID. * @type {string} */ var hexId = hexId; var /** string */ name = 'Jamie'; function useSomething(/** (string|number|!Object) */ something) { ... } |
@typedef
|
Déclare un alias pour un type plus complexe. Actuellement, les typedefs ne peuvent être définis qu'au niveau supérieur, et non à l'intérieur des fonctions. Nous avons corrigé cette limitation dans la nouvelle inférence de type. Exemple : /** @typedef {(string|number)} */ goog.NumberLike; /** @param {goog.NumberLike} x A number or a string. */ goog.readNumber = function(x) { ... } |
@unrestricted
|
Indique qu'une classe n'est ni de type Exemple : /** * @constructor * @unrestricted */ function Foo(x) { this.x = x; } var obj1 = new Foo(123); var someVar = obj1.x; // OK obj1.x = "qwerty"; // OK obj1['x'] = "asdf"; // OK obj1.y = 5; // OK |
Expressions de type
Vous pouvez spécifier le type de données de n'importe quelle variable, propriété, expression ou paramètre de fonction avec une expression de type. Une expression de type se compose d'accolades ("{ }") contenant une combinaison des opérateurs de type décrits ci-dessous.
Utilisez une expression de type avec la balise @param
pour déclarer le type d'un paramètre de fonction. Utilisez une expression de type avec le tag @type
pour déclarer le type d'une variable, d'une propriété ou d'une expression.
Plus vous spécifiez de types dans votre code, plus le compilateur peut effectuer d'optimisations et détecter d'erreurs.
Le compilateur utilise ces annotations pour vérifier le type de votre programme.
Notez que Closure Compiler ne garantit pas qu'il sera en mesure de déterminer le type de chaque expression de votre programme. Il fait de son mieux en examinant la façon dont les variables sont utilisées et les annotations de type associées à leurs déclarations. Il utilise ensuite un certain nombre d'algorithmes d'inférence de type pour déterminer le type du plus grand nombre possible d'expressions. Certains de ces algorithmes sont simples ("si x est un nombre et que nous voyons y = x;
, alors y est un nombre"). Certaines sont plus indirectes ("si le premier paramètre de f est documenté comme un rappel qui doit prendre un nombre, et que nous voyons f(function(x) { /** ... */ });
, alors x doit être un nombre").
Nom de l'opérateur | Exemples de syntaxe | Description |
---|---|---|
Nom du type |
{boolean} {Window} {goog.ui.Menu}
|
Spécifie le nom d'un type. |
Type d'application |
{Array<string>} Tableau de chaînes.
|
Paramètre un type avec un ensemble d'arguments de type. Semblable aux génériques Java. |
Union de types |
{(number|boolean)} Nombre ou valeur booléenne. Notez les parenthèses, qui sont obligatoires. |
Indique qu'une valeur peut être de type A OU de type B. |
Type d'enregistrement |
{{myNum: number, myObject}}
Type anonyme avec une propriété nommée myNum
dont la valeur est de type number et une propriété
nommée myObject dont la valeur est de n'importe quel type.
|
Indique que la valeur comporte les membres spécifiés avec des valeurs des types spécifiés. Les accolades font partie de la syntaxe de type. Par exemple, pour désigner un |
Type pouvant avoir une valeur nulle |
{?number} Un nombre ou null .
|
Indique qu'une valeur est de type A ou Tous les types d'objets sont annulables par défaut, qu'ils soient déclarés ou non avec l'opérateur Nullable. Un type d'objet est défini comme tout élément autre qu'une fonction, une chaîne, un nombre ou une valeur booléenne. Pour rendre un type d'objet non nullable, utilisez l'opérateur Non-nullable. |
Type non nullable |
{!Object} : un objet, mais jamais la valeur null .
|
Indique qu'une valeur est de type A et n'est pas nulle. Les fonctions et tous les types de valeurs (booléen, nombre et chaîne) sont non nullables par défaut, qu'ils soient déclarés ou non avec l'opérateur Non-nullable. Pour qu'un type de valeur ou de fonction puisse avoir une valeur nulle, utilisez l'opérateur Nullable. |
Type de fonction |
{function(string, boolean)} Fonction qui accepte deux paramètres (une chaîne et un booléen) et dont la valeur renvoyée est inconnue. |
Spécifie une fonction et les types de paramètres de la fonction. |
Type de retour de la fonction |
{function(): number} Fonction qui ne prend aucun paramètre et renvoie un nombre. |
Spécifie le type de valeur renvoyée d'une fonction. |
Type de fonction this |
{function(this:goog.ui.Menu, string)} Fonction qui accepte un paramètre (une chaîne) et s'exécute dans le contexte d'un goog.ui.Menu. |
Spécifie le type de la valeur de this dans la fonction. |
Type de fonction new |
{function(new:goog.ui.Menu, string)} Fonction qui accepte un paramètre (une chaîne) et crée une instance de goog.ui.Menu lorsqu'elle est appelée avec le mot clé "new". |
Spécifie le type construit d'un constructeur. |
Paramètres variables |
{function(string, ...number): number} Fonction qui accepte un paramètre (une chaîne), puis un nombre variable de paramètres qui doivent être des nombres. |
Indique qu'un type de fonction accepte un nombre variable de paramètres et spécifie un type pour les paramètres variables. |
Paramètres de variable (dans les annotations @param )
|
@param {...number} var_args Nombre variable de paramètres pour une fonction annotée. |
Indique que la fonction annotée accepte un nombre variable de paramètres et spécifie un type pour les paramètres variables. |
Paramètre facultatif dans une annotation @param
|
@param {number=} opt_argument Paramètre facultatif de type number .
|
Indique que l'argument décrit par une annotation
Si un appel de méthode omet un paramètre facultatif, cet argument aura une valeur de /** * Some class, initialized with an optional value. * @param {Object=} opt_value Some value (optional). * @constructor */ function MyClass(opt_value) { /** * Some value. * @type {Object|undefined} */ this.myValue = opt_value; } |
Argument facultatif dans un type de fonction |
{function(?string=, number=)} Fonction qui accepte une chaîne nullable facultative et un nombre facultatif comme arguments. |
Indique qu'un argument dans un type de fonction est facultatif. Un argument facultatif peut être omis de l'appel de fonction. Dans la liste des arguments, un argument facultatif ne peut pas précéder un argument non facultatif. |
Type ALL | {*} |
Indique que la variable peut prendre n'importe quel type. |
Type UNKNOWN | {?} |
Indique que la variable peut prendre n'importe quel type et que le compilateur ne doit pas vérifier le type de ses utilisations. |
Casting des types
Pour caster une valeur dans un type spécifique, utilisez la syntaxe suivante :
/** @type {!MyType} */ (valueExpression)
Types génériques
Tout comme Java, le compilateur Closure est compatible avec les types, fonctions et méthodes génériques. Les génériques fonctionnent sur des objets de différents types tout en préservant la sécurité des types au moment de la compilation.
Vous pouvez utiliser des génériques pour implémenter des collections généralisées qui contiennent des références à des objets d'un type particulier, ainsi que des algorithmes généralisés qui fonctionnent sur des objets d'un type particulier.
Déclarer un type générique
Un type peut être rendu générique en ajoutant une annotation @template
au constructeur du type (pour les classes) ou à la déclaration d'interface (pour les interfaces). Exemple :
/** * @constructor * @template T */ Foo = function() { ... };
L'annotation @template T
indique que Foo
est un type générique avec un type de modèle, T
.
Le type de modèle T
peut être utilisé comme type dans le champ d'application de la définition de Foo
. Exemple :
/** @return {T} */ Foo.prototype.get = function() { ... }; /** @param {T} t */ Foo.prototype.set = function(t) { ... };
La méthode get
renvoie un objet de type T
, et la méthode set
n'accepte que les objets de type T
.
Instancier un type générique
En réutilisant l'exemple ci-dessus, une instance basée sur un modèle Foo
peut être créée de plusieurs manières :
/** @type {!Foo<string>} */ var foo = new Foo(); var foo = /** @type {!Foo<string>} */ (new Foo());
Les deux instructions de constructeur ci-dessus créent une instance Foo
dont le type de modèle T
est string
. Le compilateur s'assurera que les appels aux méthodes de foo
et les accès aux propriétés de foo
respectent le type de modèle. Exemple :
foo.set("hello"); // OK. foo.set(3); // Error - expected a string, found a number. var x = foo.get(); // x is a string.
Les instances peuvent également être typées de manière implicite par leurs arguments de constructeur.
Prenons un autre type générique, Bar
:
/** * @param {T} t * @constructor * @template T */ Bar = function(t) { ... }; var bar = new Bar("hello"); // bar is a Bar<string>
Le type de l'argument du constructeur Bar
est inféré comme string
. Par conséquent, l'instance créée bar
est inférée comme Bar<string>
.
Plusieurs types de modèles
Un générique peut comporter un nombre illimité de types de modèles. La classe de carte suivante comporte deux types de modèles :
/** * @constructor * @template Key, Val */ MyMap = function() { ... };
Tous les types de modèles pour un type générique doivent être spécifiés dans la même annotation @template
, sous forme de liste séparée par des virgules. L'ordre des noms de types de modèles est important, car les annotations de type de modèle utiliseront l'ordre pour associer les types de modèles aux valeurs. Exemple :
/** @type {MyMap<string, number>} */ var map; // Key = string, Val = number.
Invariance des types génériques
Le compilateur Closure impose une saisie générique invariante. Cela signifie que si un contexte attend un type Foo<X>
, vous ne pouvez pas transmettre un type Foo<Y>
lorsque X
et Y
sont des types différents, même si l'un est un sous-type de l'autre. Exemple :
/** * @constructor */ X = function() { ... }; /** * @extends {X} * @constructor */ Y = function() { ... }; /** @type {Foo<X>} */ var fooX; /** @type {Foo<Y>} */ var fooY; fooX = fooY; // Error fooY = fooX; // Error /** @param {Foo<Y>} fooY */ takesFooY = function(fooY) { ... }; takesFooY(fooY); // OK. takesFooY(fooX); // Error
Héritage des types génériques
Les types génériques peuvent être hérités, et leurs types de modèles peuvent être fixes ou propagés au type hérité. Voici un exemple de type hérité corrigeant le type de modèle de son supertype :
/** * @constructor * @template T */ A = function() { ... }; /** @param {T} t */ A.prototype.method = function(t) { ... }; /** * @constructor * @extends {A<string>} */ B = function() { ... };
En étendant A<string>
, B
aura une méthode method
qui prend un paramètre de type string
.
Voici un exemple de type hérité propageant le type de modèle de son supertype :
/** * @constructor * @template U * @extends {A<U>} */ C = function() { ... };
En étendant A<U>
, les instances de C
basées sur un modèle auront une méthode method
qui accepte un paramètre de type de modèle U
.
Les interfaces peuvent être implémentées et étendues de manière similaire, mais un seul type ne peut pas implémenter la même interface plusieurs fois avec différents types de modèles. Exemple :
/** * @interface * @template T */ Foo = function() {}; /** @return {T} */ Foo.prototype.get = function() {}; /** * @constructor * @implements {Foo<string>} * @implements {Foo<number>} */ FooImpl = function() { ... }; // Error - implements the same interface twice
Fonctions et méthodes génériques
Comme les types génériques, les fonctions et les méthodes peuvent être rendues génériques en ajoutant une annotation @template
à leur définition. Exemple :
/** * @param {T} a * @return {T} * @template T */ identity = function(a) { return a; }; /** @type {string} */ var msg = identity("hello") + identity("world"); // OK /** @type {number} */ var sum = identity(2) + identity(2); // OK /** @type {number} */ var sum = identity(2) + identity("2"); // Type mismatch