Remarque: Cette page est obsolète. La liste complète est disponible à l'adresse https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler.
Présentation
Closure Compiler peut utiliser les informations de type de données sur les variables JavaScript pour améliorer l'optimisation et afficher des avertissements. Toutefois, JavaScript ne permet pas de déclarer des types.
Comme JavaScript n'a pas de 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 type de Closure Compiler est dérivé des annotations utilisées par l'outil de génération de documents JSDoc, bien qu'il ait depuis divergé. Il inclut désormais plusieurs annotations non compatibles avec JSDoc, et inversement. Ce document décrit l'ensemble d'annotations et d'expressions de type acceptées par le Closure Compiler.
Balises JSDoc
Closure Compiler recherche des informations de type dans les tags 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 qu'il ne comporte pas d'erreurs de type et d'autres erreurs.
Ce tableau n'inclut que les balises qui affectent le comportement de Closure Compiler. Pour en savoir plus sur les autres balises JSDoc, consultez la documentation du kit JSDoc.
Balise | Description |
---|---|
@abstract
|
Marque une méthode comme abstraite. À l'instar de 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 intégrer des variables La déclaration du type est facultative.
Le compilateur génère un avertissement si une valeur est attribuée à une variable plusieurs fois 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 en tant que constructeur.
Le compilateur nécessite une annotation Exemple : /** * A rectangle. * @constructor */ function GM_Rect() { ... } |
@define
|
Indique une constante pouvant ê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'énumération. Une énumération est un objet dont les propriétés constituent un ensemble de constantes associées. Le tag 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
|
Avec ce code /** @export */ foo.MyPublicClass.prototype.myPublicMethod = function() { // ... };
Lorsque le compilateur est exécuté avec l'option goog.exportProperty(foo.MyPublicClass.prototype, 'myPublicMethod', foo.MyPublicClass.prototype.myPublicMethod); qui exportera les symboles vers du 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 de mise en œuvre de l'héritage, consultez la page sur la fonction Closure Library 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 taguez un constructeur à l'aide de 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 des déclarations de propriété externes.
La propriété possède 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 qu'elle contient exactement la même documentation. Notez que le tag Exemple : /** @inheritDoc */ project.SubClass.prototype.toString = function() { ... }; |
@interface
|
Marque une fonction en tant qu'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. Consultez
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 les 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 ne correspond pas à un nom de type comme dans les autres annotations. Il s'agit d'un nom d'objet. Elle nomme l'objet auquel les propriétés sont prêtées.
Par exemple, La documentation du kit JSDoc contient 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 de droits d'auteur) de rester inchangé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
|
Indique une propriété qui ne doit pas être réduite par le compilateur en une variable. La principale utilisation 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 de retour 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 super-classe. Exemple : /** * @return {string} Human-readable representation of * project.SubClass. * @override */ project.SubClass.prototype.toString = function() { ... }; |
@package
|
Marque un membre ou une propriété comme privé. Seul le code du même répertoire peut accéder aux noms marqués
Les constructeurs publics peuvent disposer de 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éthode, de fonction et de constructeur pour spécifier les types d'arguments de la fonction. Les tags
Le tag
Vous pouvez également annoter les types de paramètres intégrés (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; }Pour les paramètres qui représentent un modèle de déstructuration, vous pouvez utiliser n'importe quel nom correspondant à un identifiant JS valide après l'annotation de type. /** * @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 fonctions et variables globales marquées
Les propriétés statiques publiques des constructeurs marqués comme Exemple : /** * Handlers that are listening to this logger. * @private {Array<Function>} */ this.handlers_ = []; |
@protected
|
Indique qu'un membre ou une propriété est protégé.
Une propriété marquée comme
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 une interface structurelle. Une interface structurelle est semblable à une 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 renvoi des définitions de méthode et de fonction.
Le tag
Vous pouvez également annoter le type de retour intégré (voir la fonction
Si une fonction qui n'est pas dans des externs n'a pas de valeur renvoyée, vous pouvez omettre le tag 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ée pour documenter les exceptions générées par une fonction. L'outil de vérification des types n'utilise pas ces informations pour le moment. Elle ne sert qu'à déterminer si une fonction déclarée dans un fichier externe 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. Le tag Lorsque vous déclarez un paramètre de variable ou de fonction, vous pouvez écrire l'annotation de type de façon intégrée 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 types de définition ne peuvent être définis qu'au niveau supérieur, et non à l'intérieur des fonctions. Nous avons corrigé cette limite dans l'inférence de nouveau 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 est constituée 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 la balise @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 optimiser les optimisations et plus il peut 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 dans votre programme. Nous nous efforcerons de vérifier la façon dont les variables sont utilisées et les annotations de types associées à leurs déclarations. Ensuite, elle utilise un certain nombre d'algorithmes d'inférence de type pour déterminer le type d'un maximum d'expressions. Certains de ces algorithmes sont simples ("si x est un nombre et que nous voyons y = x;
, alors y est un nombre"). Certains sont plus indirects (si le premier paramètre de f est documenté en tant que rappel devant accepter un nombre et que nous observons 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 : Application |
{Array<string>} Tableau de chaînes.
|
Paramètre un type avec un ensemble d'arguments de type. Semblable aux génériques Java. |
Type Union |
{(number|boolean)} Nombre ou valeur booléenne. Notez les parenthèses, qui sont obligatoires. |
Indique qu'une valeur peut être de type A OU 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 comprend les membres spécifiés avec les valeurs des types spécifiés. Les accolades font partie de la syntaxe des types. Par exemple, pour indiquer une propriété |
Type null |
{?number} Un nombre ou null .
|
Indique qu'une valeur est de type A ou Tous les types d'objets peuvent être vides par défaut, qu'ils soient déclarés à l'aide de l'opérateur Nullable ou non. Un type d'objet est défini comme n'importe quel élément à l'exception d'une fonction, d'une chaîne, d'un nombre ou d'une valeur booléenne. Pour rendre un type d'objet ne pouvant être vide, utilisez l'opérateur Non-nullable. |
Type ne pouvant être vide |
{!Object} Un objet, mais jamais la valeur null .
|
Indique qu'une valeur est de type A et non nulle. Les fonctions et tous les types de valeurs (booléen, nombre et chaîne) ne peuvent pas être nuls par défaut, qu'ils soient déclarés ou non avec l'opérateur "Non nul". Pour rendre une valeur ou un type de fonction pouvant être vide, utilisez l'opérateur Nullable. |
Type de fonction |
{function(string, boolean)} Fonction qui accepte deux paramètres (une chaîne et une valeur booléenne) et dont la valeur affichée est inconnue. |
Spécifie une fonction et les types de ses paramètres. |
Type de renvoi de la fonction |
{function(): number} Une fonction qui ne prend aucun paramètre et renvoie un nombre. |
Spécifie le type de valeur renvoyée par une fonction. |
Type de fonction this |
{function(this:goog.ui.Menu, string)} Fonction qui prend un paramètre (une chaîne) et s'exécute dans le contexte d'un goog.ui.Menu. |
Spécifie le type de valeur de this dans la fonction. |
Type de fonction new |
{function(new:goog.ui.Menu, string)} Fonction qui utilise 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 de variable |
{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 des variables. |
Paramètres variables (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 de la variable. |
Paramètre facultatif d'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 la valeur /** * 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 utilise une chaîne facultative nul 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. Un argument facultatif ne peut pas précéder un argument non facultatif de la liste des arguments. |
Le type ALL [TOUTES] | {*} |
Indique que la variable peut accepter n'importe quel type. |
Type UNKNOWN | {?} |
Indique que la variable peut accepter n'importe quel type, et que le compilateur ne doit en vérifier aucune utilisation. |
Caster un type
Pour caster une valeur vers un type spécifique, utilisez cette syntaxe
/** @type {!MyType} */ (valueExpression)Les parenthèses entourant l'expression sont toujours obligatoires.
Types génériques
Tout comme Java, Closure Compiler est compatible avec les types, fonctions et méthodes génériques. Les caractères génériques opèrent sur des objets de différents types tout en préservant la sécurité du type de 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, et des algorithmes généralisés qui agissent sur des objets d'un type particulier.
Déclarer un type générique
Un type peut être 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 de champ d'application dans 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
.
Instanciation d'un type générique
En reprenant l'exemple ci-dessus, une instance modélisée de 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 appliquera les appels aux méthodes de foo
et l'accès aux propriétés de foo
, tout en respectant 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 tapées implicitement par leurs arguments de constructeur.
Prenons l'exemple d'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 déduit en tant que string
. Par conséquent, l'instance créée bar
est déduite en tant que Bar<string>
.
Plusieurs types de modèles
Un modèle générique peut avoir 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 d'un type générique doivent être spécifiés dans la même annotation @template
, sous la forme d'une liste d'éléments séparés par une virgule. L'ordre des noms de types de modèles est important, car les annotations de type de modèle utilisent l'ordre pour associer les types de modèle aux valeurs. Exemple :
/** @type {MyMap<string, number>} */ var map; // Key = string, Val = number.
Invariance des types génériques
Closure Compiler applique 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èle peuvent être corrigés ou propagés vers le type hérité. Voici un exemple de type héritant qui corrige 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
possède une méthode method
qui utilise un paramètre de type string
.
Voici un exemple de type héroïque propageant le type de modèle de son supertype:
/** * @constructor * @template U * @extends {A<U>} */ C = function() { ... };
Si vous étendez A<U>
, les instances modélisées de C
auront une méthode method
qui accepte un paramètre du type de modèle U
.
Les interfaces peuvent être implémentées et étendues de la même manière, mais un même type ne peut pas implémenter la même interface plusieurs fois avec des types de modèles différents. 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 pour les types génériques, les fonctions et les méthodes peuvent être 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