Observação: esta página está desatualizada. A lista completa é mantida em https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler
Visão geral
O Closure Compiler pode usar informações de tipo de dados sobre variáveis JavaScript para fornecer otimização e avisos aprimorados. O JavaScript, no entanto, não tem como declarar tipos.
Como o JavaScript não tem uma sintaxe para declarar o tipo de uma variável, é necessário usar comentários no código para especificar o tipo de dados.
A linguagem de tipo do Closure Compiler deriva das anotações usadas pela ferramenta de geração de documentos JSDoc, embora tenha divergido desde então. Agora ele inclui várias anotações que o JSDoc não aceita e vice-versa. Este documento descreve o conjunto de anotações e expressões de tipo que o Closure Compiler entende.
Tags JSDoc
O Closure Compiler procura informações de tipo em tags JSDoc. Use as tags JSDoc descritas na tabela de referência abaixo para ajudar o compilador a otimizar seu código e verificar possíveis erros de tipo e outros erros.
Essa tabela inclui apenas tags que afetam o comportamento do Closure Compiler. Para informações sobre outras tags do JSDoc, consulte a documentação do JSDoc Toolkit.
Tag | Descrição |
---|---|
@abstract
|
Marca um método como abstrato. Assim como ao definir um método como
O compilador gera um aviso se um método marcado
com /** @abstract */ foo.MyClass.prototype.abstractMethod = function() {}; |
@const
|
Marca uma variável como somente leitura. O compilador pode
inserir variáveis A declaração de tipo é opcional.
O compilador gera um aviso se uma variável marcada
com /** @const */ var MY_BEER = 'stout'; /** * My namespace's favorite kind of beer. * @const {string} */ mynamespace.MY_BEER = 'stout'; /** @const */ MyClass.MY_BEER = 'stout'; |
@constructor
|
Marca uma função como um construtor.
O compilador exige uma anotação Exemplo: /** * A rectangle. * @constructor */ function GM_Rect() { ... } |
@define
|
Indica uma constante que pode ser substituída pelo compilador no momento da compilação.
Com o exemplo à esquerda, é possível transmitir a flag
--define='ENABLE_DEBUG=false'
ao compilador para mudar o valor de
ENABLE_DEBUG para false.
O tipo de uma constante definida pode ser número, string ou booleano.
As definições só são permitidas no escopo global.
Exemplo: /** @define {boolean} */ var ENABLE_DEBUG = true; /** @define {boolean} */ goog.userAgent.ASSUME_IE = false; |
@deprecated
|
Marca uma função, um método ou uma propriedade para que o uso dela produza um aviso do compilador indicando que ela não deve mais ser usada. Exemplo: /** * 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
|
O Exemplo: /** * @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
|
Especifica o tipo de uma enumeração. Uma enumeração é um objeto cujas propriedades
constituem um conjunto de constantes relacionadas. A tag O rótulo de tipo de uma enumeração se aplica a cada propriedade dela. Por exemplo, se uma enumeração tiver o tipo Exemplo: /** * Enum for tri-state values. * @enum {number} */ project.TriState = { TRUE: 1, FALSE: -1, MAYBE: 0 }; |
@export
|
Dado este código /** @export */ foo.MyPublicClass.prototype.myPublicMethod = function() { // ... };
Quando o compilador é executado com a flag goog.exportProperty(foo.MyPublicClass.prototype, 'myPublicMethod', foo.MyPublicClass.prototype.myPublicMethod); que vai exportar os símbolos para o código não compilado. Você pode escrever /** * @export * @type {SomeType} */ O código que usa a anotação
|
@extends
|
Marca uma classe ou interface como herdeira de outra classe. Uma classe marcada com
Observação:
Para um exemplo de implementação de herança, consulte
a função da biblioteca
Closure Exemplo: /** * Immutable empty node list. * @constructor * @extends {goog.ds.BasicNodeList} */ goog.ds.EmptyNodeList = function() { ... }; |
@final
|
Indica que essa classe não pode ser estendida. Para métodos, indica que nenhuma subclasse pode substituir esse método. Exemplo: /** * A class that cannot be extended. * @final * @constructor */ sloth.MyFinalClass = function() { ... } /** * A method that cannot be overridden. * @final */ sloth.MyFinalClass.prototype.method = function() { ... }; |
@implements
|
Usado com
O compilador gera um aviso se você marcar um construtor
com Exemplo: /** * A shape. * @interface */ function Shape() {}; Shape.prototype.draw = function() {}; /** * @constructor * @implements {Shape} */ function Square() {}; Square.prototype.draw = function() { ... }; |
@implicitCast
|
Essa anotação só pode aparecer em declarações de propriedades externas.
A propriedade tem um tipo declarado, mas você pode atribuir qualquer tipo a ela sem um aviso. Ao acessar a propriedade, você recebe um valor do tipo declarado. Por exemplo, /** * @type {string} * @implicitCast */ Element.prototype.innerHTML; |
@inheritDoc
|
Indica que um método ou propriedade de uma subclasse
oculta intencionalmente um método ou propriedade da superclasse e tem
exatamente a mesma documentação. A tag Exemplo: /** @inheritDoc */ project.SubClass.prototype.toString = function() { ... }; |
@interface
|
Marca uma função como uma interface. Uma interface especifica os
membros obrigatórios de um tipo. Qualquer classe que implemente uma interface
precisa implementar todos os métodos e propriedades definidos no
protótipo
da interface. Veja
O compilador verifica se as interfaces não são instanciadas. Se a palavra-chave Exemplo: /** * A shape. * @interface */ function Shape() {}; Shape.prototype.draw = function() {}; /** * A polygon. * @interface * @extends {Shape} */ function Polygon() {}; Polygon.prototype.getSides = function() {}; |
@lends
|
Indica que as chaves de um literal de objeto devem ser tratadas como propriedades de algum outro objeto. Essa anotação só deve aparecer em literais de objeto.
O nome entre chaves não é um nome de tipo como em outras anotações. É um nome de objeto. Ele nomeia o objeto a que as propriedades são emprestadas.
Por exemplo, A documentação do JSDoc Toolkit tem mais informações sobre essa anotação. Exemplo: goog.object.extend( Button.prototype, /** @lends {Button.prototype} */ ({ isButton: function() { return true; } })); |
@license ou @preserve
|
Instrui o compilador a inserir o comentário associado antes do código compilado do arquivo marcado. Essa anotação permite que avisos importantes (como licenças legais ou texto de direitos autorais) sobrevivam à compilação sem alterações. As quebras de linha são preservadas. Exemplo: /** * @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
|
Indica uma propriedade que não deve ser recolhida pelo compilador em uma variável. O principal uso de Exemplo: /** * A namespace. * @const */ var foo = {}; /** * @nocollapse */ foo.bar = 42; window['foobar'] = foo.bar; |
@nosideeffects
|
Indica que uma chamada para a função externa declarada não tem efeitos colaterais.
Essa anotação permite que o compilador remova chamadas para a função
se o valor de retorno não for usado. A anotação só é permitida em
Exemplo: /** @nosideeffects */ function noSideEffectsFn1() {} /** @nosideeffects */ var noSideEffectsFn2 = function() {}; /** @nosideeffects */ a.prototype.noSideEffectsFn3 = function() {}; |
@override
|
Indica que um método ou propriedade de uma subclasse oculta intencionalmente um método ou propriedade da superclasse. Se nenhuma outra anotação for incluída, o método ou a propriedade vai herdar automaticamente as anotações da superclasse. Exemplo: /** * @return {string} Human-readable representation of * project.SubClass. * @override */ project.SubClass.prototype.toString = function() { ... }; |
@package
|
Marca um membro ou propriedade como pacote particular. Apenas o código no mesmo diretório
pode acessar nomes marcados como
Os construtores públicos podem ter propriedades Exemplo: /** * 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
|
Usado com definições de método, função e construtor para especificar
os tipos de argumentos de função. As tags
A tag
Como alternativa, você pode anotar os tipos dos parâmetros inline
(consulte a função Exemplo: /** * 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
|
Marca um membro como particular. Apenas o código no mesmo arquivo pode acessar variáveis e funções globais marcadas como
As propriedades estáticas públicas de construtores marcados como Exemplo: /** * Handlers that are listening to this logger. * @private {Array<Function>} */ this.handlers_ = []; |
@protected
|
Indica que um membro ou uma propriedade está protegida.
Uma propriedade marcada como
Exemplo: /** * 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
|
Marca uma função como uma interface estrutural. Uma interface estrutural
é semelhante a uma Exemplo: /** * 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
|
Especifica os tipos de retorno de definições de método e função.
A tag
Como alternativa, você pode anotar o tipo de retorno inline
(consulte a função
Se uma função que não está em externs não tiver um valor de retorno, omita a tag
Exemplo: /** * 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
|
Exemplo: /** * @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
|
Consulte Tipos genéricos. Exemplo: /** * @param {T} t * @constructor * @template T */ Container = function(t) { ... }; |
@this
|
Especifica o tipo do objeto a que a palavra-chave
Para evitar avisos do compilador, use
uma anotação Exemplo: chat.RosterWidget.extern('getRosterElement', /** * Returns the roster widget element. * @this {Widget} * @return {Element} */ function() { return this.getComponent().getElement(); }); |
@throws
|
Usado para documentar as exceções geradas por uma função. No momento, o verificador de tipos não usa essas informações. Ele só é usado para descobrir se uma função declarada em um arquivo de externs tem efeitos colaterais. Exemplo: /** * @throws {DOMException} */ DOMApplicationCache.prototype.swapCache = function() { ... }; |
@type
|
Identifica o tipo de uma variável, propriedade ou expressão. A tag Ao declarar uma variável ou um parâmetro de função,
é possível escrever a anotação de tipo inline omitindo
Exemplo: /** * The message hex ID. * @type {string} */ var hexId = hexId; var /** string */ name = 'Jamie'; function useSomething(/** (string|number|!Object) */ something) { ... } |
@typedef
|
Declara um alias para um tipo mais complexo. No momento, os typedefs só podem ser definidos no nível superior, não dentro de funções. Corrigimos essa limitação na nova inferência de tipo. Exemplo: /** @typedef {(string|number)} */ goog.NumberLike; /** @param {goog.NumberLike} x A number or a string. */ goog.readNumber = function(x) { ... } |
@unrestricted
|
Indica que uma classe não é um tipo Exemplo: /** * @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 |
Expressões de tipo
É possível especificar o tipo de dados de qualquer variável, propriedade, expressão ou parâmetro de função com uma expressão de tipo. Uma expressão de tipo consiste em chaves ("{ }") que contêm alguma combinação dos operadores de tipo descritos abaixo.
Use uma expressão de tipo com a tag @param
para declarar o tipo de um parâmetro de função. Use uma expressão de tipo com
a tag @type
para declarar o
tipo de uma variável, propriedade ou expressão.
Quanto mais tipos você especificar no código, mais otimizações o compilador poderá fazer e mais erros ele poderá detectar.
O compilador usa essas anotações para verificar o tipo do seu programa.
O Closure Compiler não garante que vai conseguir descobrir o tipo de todas as expressões no seu programa. Ele faz o possível para analisar como as variáveis são usadas e as anotações de tipo anexadas às declarações delas. Em seguida, ele usa vários algoritmos de inferência de tipo para
descobrir o tipo do maior número possível de expressões. Alguns desses algoritmos são simples ("se x for um número e encontrarmos y = x;
, então y será um número"). Algumas são mais indiretas ("se o primeiro parâmetro de f for documentado como um callback que precisa receber um número e encontrarmos f(function(x) { /** ... */ });
, x precisa ser um número").
Nome do operador | Exemplos de sintaxe | Descrição |
---|---|---|
Nome do tipo |
{boolean} {Window} {goog.ui.Menu}
|
Especifica o nome de um tipo. |
Type Application |
{Array<string>} Uma matriz de strings.
|
Parametriza um tipo com um conjunto de argumentos de tipo. Semelhante aos tipos genéricos do Java. |
União de tipos |
{(number|boolean)} Um número ou um booleano. Observe os parênteses, que são obrigatórios. |
Indica que um valor pode ter o tipo A OU o tipo B. |
Tipo de registro |
{{myNum: number, myObject}}
Um tipo anônimo com uma propriedade chamada myNum
que tem um valor do tipo number e uma propriedade
chamada myObject que tem um valor de qualquer tipo.
|
Indica que o valor tem os membros especificados com valores dos tipos especificados. As chaves fazem parte da sintaxe de tipo. Por exemplo, para
denotar um |
Tipo anulável |
{?number} Um número ou null .
|
Indica que um valor é do tipo A ou Por padrão, todos os tipos de objeto são anuláveis, sejam ou não declarados com o operador Nullable. Um tipo de objeto é definido como qualquer coisa, exceto uma função, string, número ou booleano. Para tornar um tipo de objeto não anulável, use o operador Non-nullable. |
Tipo não anulável |
{!Object} Um objeto, mas nunca o valor null .
|
Indica que um valor é do tipo A e não é nulo. As funções e todos os tipos de valor (booleano, número e string) são não anuláveis por padrão, sejam ou não declarados com o operador "Non-nullable". Para tornar um valor ou tipo de função anulável, use o operador Nullable. |
Tipo de função |
{function(string, boolean)} Uma função que usa dois parâmetros (uma string e um booleano) e tem um valor de retorno desconhecido. |
Especifica uma função e os tipos dos parâmetros dela. |
Tipo de retorno da função |
{function(): number} Uma função que não usa parâmetros e retorna um número. |
Especifica o tipo de um valor de retorno de função. |
Tipo de função this |
{function(this:goog.ui.Menu, string)} Uma função que usa um parâmetro (uma string) e é executada no contexto de um goog.ui.Menu. |
Especifica o tipo do valor de this na função. |
Tipo de função new |
{function(new:goog.ui.Menu, string)} Uma função que usa um parâmetro (uma string) e cria uma nova instância de goog.ui.Menu quando chamada com a palavra-chave "new". |
Especifica o tipo construído de um construtor. |
Parâmetros variáveis |
{function(string, ...number): number} Uma função que usa um parâmetro (uma string) e um número variável de parâmetros que precisam ser números. |
Indica que um tipo de função usa um número variável de parâmetros e especifica um tipo para os parâmetros variáveis. |
Parâmetros de variável (em anotações @param )
|
@param {...number} var_args Um número variável de parâmetros para uma função anotada. |
Indica que a função anotada aceita um número variável de parâmetros e especifica um tipo para os parâmetros variáveis. |
Parâmetro opcional em uma anotação @param
|
@param {number=} opt_argument Um parâmetro opcional do tipo number .
|
Indica que o argumento descrito por uma anotação
Se uma chamada de método omitir um parâmetro opcional, esse argumento terá um valor 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; } |
Argumento opcional em um tipo de função |
{function(?string=, number=)} Uma função que usa uma string anulável opcional e um número opcional como argumentos. |
Indica que um argumento em um tipo de função é opcional. Um argumento opcional pode ser omitido da chamada de função. Um argumento opcional não pode preceder um argumento não opcional na lista de argumentos. |
O tipo ALL | {*} |
Indica que a variável pode assumir qualquer tipo. |
O tipo UNKNOWN | {?} |
Indica que a variável pode assumir qualquer tipo e que o compilador não deve verificar o tipo de nenhum uso dela. |
Conversão de tipo
Para converter um valor em um tipo específico, use esta sintaxe:
/** @type {!MyType} */ (valueExpression)
Tipos genéricos
Assim como o Java, o Closure Compiler é compatível com tipos, funções e métodos genéricos. Os tipos genéricos operam em objetos de vários tipos, preservando a segurança de tipo em tempo de compilação.
É possível usar tipos genéricos para implementar coleções generalizadas que contêm referências a objetos de um tipo específico e algoritmos generalizados que operam em objetos de um tipo específico.
Declaração de um tipo genérico
Um tipo pode ser genérico adicionando uma anotação @template
ao construtor do tipo (para classes) ou à declaração de interface (para interfaces). Exemplo:
/** * @constructor * @template T */ Foo = function() { ... };
A anotação @template T
indica que Foo
é um tipo genérico com um tipo de modelo, T
.
O tipo de modelo T
pode ser usado como um tipo no escopo
da definição de Foo
. Exemplo:
/** @return {T} */ Foo.prototype.get = function() { ... }; /** @param {T} t */ Foo.prototype.set = function(t) { ... };
O método get
vai retornar um objeto do tipo T
, e o método set
só vai aceitar objetos do tipo T
.
Instanciar um tipo genérico
Reutilizando o exemplo acima, uma instância com modelo de Foo
pode ser criada de várias maneiras:
/** @type {!Foo<string>} */ var foo = new Foo(); var foo = /** @type {!Foo<string>} */ (new Foo());
As duas instruções de construtor acima criam uma instância Foo
cujo tipo de modelo T
é string
. O compilador vai
forçar que as chamadas aos métodos de foo
e os acessos às
propriedades de foo
respeitem o tipo com modelo. Exemplo:
foo.set("hello"); // OK. foo.set(3); // Error - expected a string, found a number. var x = foo.get(); // x is a string.
As instâncias também podem ser digitadas implicitamente pelos argumentos do construtor.
Considere um tipo genérico diferente, Bar
:
/** * @param {T} t * @constructor * @template T */ Bar = function(t) { ... }; var bar = new Bar("hello"); // bar is a Bar<string>
O tipo do argumento para o construtor Bar
é inferido como string
e, como resultado, a instância criada bar
é inferida como Bar<string>
.
Vários tipos de modelo
Um tipo genérico pode ter qualquer número de tipos de modelo. A classe de mapa a seguir tem dois tipos de modelo:
/** * @constructor * @template Key, Val */ MyMap = function() { ... };
Todos os tipos de modelo para um tipo genérico precisam ser especificados na mesma anotação @template
, como uma lista separada por vírgulas. A ordem dos nomes de tipos de modelo é importante, já que as anotações de tipo com modelo usam a ordem para parear tipos de modelo com os valores. Exemplo:
/** @type {MyMap<string, number>} */ var map; // Key = string, Val = number.
Invariância de tipos genéricos
O Closure Compiler aplica a tipagem genérica invariante. Isso significa que, se um contexto espera um tipo Foo<X>
, não é possível transmitir um tipo Foo<Y>
quando X
e Y
são tipos diferentes, mesmo que um seja um subtipo do outro. Exemplo:
/** * @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
Herança de tipos genéricos
Os tipos genéricos podem ser herdados, e os tipos de modelo deles podem ser fixos ou propagados para o tipo de herança. Este é um exemplo de um tipo de herança que corrige o tipo de modelo do supertipo:
/** * @constructor * @template T */ A = function() { ... }; /** @param {T} t */ A.prototype.method = function(t) { ... }; /** * @constructor * @extends {A<string>} */ B = function() { ... };
Ao estender A<string>
, B
terá um método
method
que usa um parâmetro do tipo string
.
Confira um exemplo de um tipo de herança que propaga o tipo de modelo do supertipo:
/** * @constructor * @template U * @extends {A<U>} */ C = function() { ... };
Ao estender A<U>
, as instâncias com modelo de C
terão um método method
que usa um parâmetro do tipo
de modelo U
.
As interfaces podem ser implementadas e estendidas de maneira semelhante, mas um único tipo não pode implementar a mesma interface várias vezes com diferentes tipos de modelo. Exemplo:
/** * @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
Funções e métodos genéricos
Assim como os tipos genéricos, as funções e os métodos podem ser genéricos adicionando
uma anotação @template
à definição deles. Exemplo:
/** * @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