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 Frontend Compiler pode usar informações de tipos de dados sobre variáveis JavaScript para fornecer otimização e avisos aprimorados. No entanto, o JavaScript não tem como declarar tipos.
Como o JavaScript não tem sintaxe para declarar o tipo de variável, você precisa usar comentários no código para especificar o tipo de dado.
A linguagem do tipo do Compile Compiler deriva das anotações usadas pela ferramenta de geração de documentos JSDoc, embora ela tenha divergido desde então. Agora, ele inclui várias anotações não suportadas pelo JSDoc e vice-versa. Este documento descreve o conjunto de anotações e expressões de tipo que o Frontend Compiler entende.
- Tags JSDoc
- Expressões de tipo (link em inglês)
- Tipos genéricos
Tags JSDoc
O closure Compiler procura informações de tipo nas 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.
Esta tabela inclui apenas tags que afetam o comportamento do Frontend Compiler. Para mais informações sobre outras tags JSDoc, consulte a documentação do kit de ferramentas do JSDoc.
Tag | Descrição |
---|---|
@abstract
|
Marca um método como abstrato. De forma semelhante à definição de um método como
O compilador vai produzir 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 vai produzir 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 durante a compilação.
Com o exemplo à esquerda, você pode transmitir a sinalização
--define='ENABLE_DEBUG=false'
para o compilador para alterar 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, método ou propriedade para que usá-lo produza um aviso do compilador indicando que ele não deve mais ser usado. 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
|
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 com propriedades
que constituem um conjunto de constantes relacionadas. A tag O rótulo de tipo de uma enumeração é aplicado a cada propriedade da
enumeração. 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
|
Com este código /** @export */ foo.MyPublicClass.prototype.myPublicMethod = function() { // ... };
Quando o compilador é executado com a sinalização goog.exportProperty(foo.MyPublicClass.prototype, 'myPublicMethod', foo.MyPublicClass.prototype.myPublicMethod); que exportará os símbolos para o código não compilado. É possível escrever
/** * @export * @type {SomeType} */ O código que usa a anotação
|
@extends
|
Marca uma classe ou interface como herdada de outra classe. Uma classe
marcada com
Observação:
Para ver um exemplo de implementação da herança, consulte a
função Exemplo: /** * Immutable empty node list. * @constructor * @extends {goog.ds.BasicNodeList} */ goog.ds.EmptyNodeList = function() { ... }; |
@final
|
Indica que esta classe não pode ser estendida. Para métodos, indica que nenhuma subclasse tem permissão para 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 produz 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 propriedade externas.
A propriedade tem um tipo declarado, mas é possível 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. Observe que a tag Exemplo: /** @inheritDoc */ project.SubClass.prototype.toString = function() { ... }; |
@interface
|
Marca uma função como uma interface. Uma interface especifica os
membros necessários para 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 estã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 precisam ser tratadas como propriedades de algum outro objeto. Essa anotação precisa aparecer apenas em literais de objeto.
Observe que o nome entre chaves não é um nome de tipo, como em outras anotações. É o nome de um objeto. Nomear o objeto a que as propriedades são concedidas.
Por exemplo, Os documentos do JSDoc Toolkit têm mais informações sobre essa anotação. Exemplo: goog.object.extend( Button.prototype, /** @lends {Button.prototype} */ ({ isButton: function() { return true; } })); |
@license ou @preserve
|
Diz ao compilador para 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 inalterada. 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 pode ser recolhida pelo compilador em uma
variável. O principal uso do 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 herdará automaticamente as anotações da superclasse dela. Exemplo: /** * @return {string} Human-readable representation of * project.SubClass. * @override */ project.SubClass.prototype.toString = function() { ... }; |
@package
|
Marca um membro ou uma propriedade como privado. Somente o código no mesmo diretório
pode acessar nomes marcados como
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, é possível 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; }Para parâmetros que são um padrão de desestruturação, é possível usar qualquer nome que seja um identificador JS válido, após a anotação de tipo. /** * @param {{name: string, age: number}} person */ function logPerson({name, age}) { console.log(`${name} is ${age} years old`); } |
@private
|
Marca um membro como particular. Somente o código no mesmo arquivo pode acessar
variáveis globais e funções
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 com
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 das 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 externas não tem valor de retorno, é possível omitir 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, é necessário usar
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 essa informação. Ela só é usada para descobrir se uma função declarada em um arquivo externo 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 um parâmetro de função ou variável,
é possível escrever a anotação de tipo in-line omitindo o
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. Atualmente, typedefs só pode ser definido 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 é do 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
Você pode 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 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 seu programa.
O Frontend Compiler não faz nenhuma promessa de que
ele conseguirá descobrir o tipo de cada expressão no seu
programa. Essa ferramenta faz um melhor esforço analisando como as variáveis são
usadas e nos tipos de anotação anexados às
declarações. Em seguida, 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 diretos ("se x for um número, e
y = x;
for visto, então y é um número"). Algumas são mais indiretas ("se o primeiro parâmetro de f
estiver documentado como uma chamada de retorno que precisa receber um número
e virmos f(function(x) { /** ... */ });
, então x precisará
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. |
Tipo de aplicativo |
{Array<string>} Uma matriz de strings.
|
Parametriza um tipo com um conjunto de argumentos de tipo. Semelhante a genéricos em Java. |
Tipo de união |
{(number|boolean)} Um número ou um valor 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 de 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 são parte da sintaxe do tipo. Por exemplo, para
denotar um |
Tipo anulável |
{?number} Um número ou null .
|
Indica que um valor é do tipo A ou Todos os tipos de objeto são anuláveis por padrão, mesmo que não sejam declarados com o operador Nullable. Um tipo de objeto é definido como qualquer coisa, exceto 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) não são anuláveis por padrão, sejam declarados ou não com o operador não anulável. 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 nenhum parâmetro e retorna um número. |
Especifica o tipo de valor de retorno de uma 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 de 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 "novo". |
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 eles. |
Parâmetros de variável (em anotações @param )
|
@param {...number} var_args Um número variável de parâmetros em uma função com anotação. |
Indica que a função anotada aceita um número variável de parâmetros e especifica um tipo para eles. |
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 opcional e anulável 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 TODAS | {*} |
Indica que a variável pode assumir qualquer tipo. |
O tipo UNKNOWN | {?} |
Indica que a variável pode assumir qualquer tipo de intervalo, e o compilador não pode verificar nenhum uso dela. |
Transmissão de tipo
Para transmitir um valor a um tipo específico, use esta sintaxe:
/** @type {!MyType} */ (valueExpression)Os parênteses ao redor da expressão são sempre obrigatórios.
Tipos genéricos
Assim como o Java, o Frontend Compiler oferece suporte a tipos, funções e métodos genéricos. Os genéricos operam em objetos de vários tipos, preservando a segurança do tipo no momento da compilação.
É possível usar genéricos para implementar coleções generalizadas que contêm referências a objetos de um determinado tipo e algoritmos generalizados que operam em objetos de um determinado tipo.
Declarar um tipo genérico
Um tipo pode ser tornado genérico adicionando uma anotação @template
ao construtor do tipo (para classes) ou à declaração da 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
retornará um objeto do tipo T
,
e o método set
só aceitará objetos do tipo T
.
Como instanciar um tipo genérico
Reutilizando o exemplo acima, uma instância de 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 do construtor acima criam uma instância Foo
em que o tipo de modelo T
é string
. O compilador aplicará
as chamadas para os métodos de foo
e os acessos às
propriedades de foo
respeitarão o tipo de 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 implicitamente digitadas por seus argumentos de 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 genérico pode ter qualquer tipo de modelo. A classe do 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 modelo é importante, já que as anotações de tipo modelo vão usar
a ordem para parear os tipos de modelo com os valores. Exemplo:
/** @type {MyMap<string, number>} */ var map; // Key = string, Val = number.
Invariação de tipos genéricos
O Frontend Compiler aplica a digitação 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 herdeiro. Veja um exemplo de um tipo de herança que corrige o tipo de modelo do supertipo dele:
/** * @constructor * @template T */ A = function() { ... }; /** @param {T} t */ A.prototype.method = function(t) { ... }; /** * @constructor * @extends {A<string>} */ B = function() { ... };
Ao estender A<string>
, o B
terá um método
method
que usa um parâmetro do tipo string
.
Veja um exemplo de um tipo herdado propagando o tipo de modelo de seu supertipo:
/** * @constructor * @template U * @extends {A<U>} */ C = function() { ... };
Ao estender A<U>
, as instâncias do modelo 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 modo 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, funções e métodos podem ser tornados genéricos adicionando
uma anotação @template
à definição. 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