A lista abaixo mostra quais construtores são atualmente suportados quando se usa anotações JSDoc para prover informações de tipo em arquivos Javascript.
Note que tags que não estão explicitamente listadas abaixo (tais como @async
) ainda não são suportadas.
@type
@param
(ou@arg
ou@argument
)@returns
(ou@return
)@typedef
@callback
@template
@class
(ou@constructor
)@this
@extends
(ou@augments
)@enum
Extensões class
- Modificadores de Propriedades
@public
,@private
,@protected
,@readonly
O significado é usualmente o mesmo, ou um superconjunto, do significado da tag descrito em jsdoc.app. O código abaixo descreve as diferenças e demonstra em exemplos a usagem de cada tag.
Nota: Você pode usar o playground para explorar o suporte a JSDoc.
@type
Você pode usar a tag “@type” para referenciar o nome de um tipo (seja ele primitivo, definido em uma declaração Typescript ou em uma tag JSDoc “@typedef”)
Você pode usar a maioria dos tipos JSDoc e qualquer tipo do Typescript, desde o mais básico como string
até o mais avançado, como tipos condicionais.
jsTry
/*** @type {string}*/vars ;/** @type {Window} */varwin ;/** @type {PromiseLike<string>} */varpromisedString ;// Você pode especificar um Elemento HTML com propriedades da DOM/** @type {HTMLElement} */varmyElement =document .querySelector (selector );element .dataset .myData = "";
@type
pode especificar uma união — por exemplo, algo pode ser uma string ou um booleano.
jsTry
/*** @type {(string | boolean)}*/varsb ;
Note que parênteses são opcionais para uniões
jsTry
/*** @type {string | boolean}*/varsb ;
Você pode especificar tipos de vetores usando uma variedade de sintaxes:
jsTry
/** @type {number[]} */varns ;/** @type {Array.<number>} */varnds ;/** @type {Array<number>} */varnas ;
Você também pode especificar tipos de objetos literais. Por exemplo, um objeto com propriedades ‘a’ (string) e ‘b’ (número) usa a seguinte sintaxe:
jsTry
/** @type {{ a: string, b: number }} */varvar9 ;
Você pode especificar objetos semelhantes a maps e semelhantes a vetores usando string e assinaturas de índice numérico, usando sintaxe JSDoc padrão ou sintaxe Typescript.
jsTry
/*** Um objeto semelhante a um map que mapeia propriedades `string` arbitrárias para `number`s.** @type {Object.<string, number>}*/varstringToNumber ;/** @type {Object.<number, object>} */vararrayLike ;
Os dois tipos precedentes são equivalentes aos tipos { [x: string]: number }
e { [x: number]: any }
do Typescript.
O compilador entende ambas as sintaxes.
Você pode especificar tipos de funções usando sintaxe Typescript ou sintaxe Closure You can specify function types using either TypeScript or Closure syntax:
jsTry
/** @type {function(string, boolean): number} sintaxe Closure */varsbn ;/** @type {(s: string, b: boolean) => number} sintaxe TypeScript */varsbn2 ;
Ou você pode usar o tipo não especificado Function
:
jsTry
/** @type {Function} */varfn7 ;/** @type {function} */varfn6 ;
Outros tipos de Closure também são aceitos:
jsTry
/*** @type {*} - pode ser o tipo 'any'*/varstar ;/*** @type {?} - tipo desconhecido (o mesmo que 'any')*/varquestion ;
Conversões
Typescript pega emprestada a sintaxe de conversão de Closure.
Isso possibilita que você converta um tipo para outro adicionando a tag @type
antes de qualquer expressão com parênteses.
jsTry
/*** @type {number | string}*/varnumberOrString =Math .random () < 0.5 ? "hello" : 100;vartypeAssertedNumber = /** @type {number} */ (numberOrString );
Importando tipos
Você também pode importar declarações de tipos a partir de outros arquivos usando importação de tipos Essa sintaxe é especifica do Typescript e difere do uso de JSDoc padrão:
jsTry
// @filename: types.d.tsexport typePet = {name : string,};// @filename: main.js/*** @param p { import("./types").Pet }*/functionwalk (p ) {console .log (`Walking ${p .name }...`);}
importação de tipos também pode ser usada em declaração de apelidos de tipos:
jsTry
/*** @typedef { import("./types").Pet } Pet*//*** @type {Pet}*/varmyPet ;myPet .name ;
importação de tipos pode ser usada para descobrir o tipo de um valor de um módulo se você ainda não sabe o tipo dele, ou se for um tipo longo que é irritante de se digitar:
jsTry
/*** @type {typeof import("./accounts").userAccount }*/varx =require ("./accounts").userAccount ;
@param
e @returns
@param
usa a mesma sintaxe que a tag @type
, porém é adicionado o nome do parâmetro.
O parâmetro também pode ser declarado como opcional se for envolvido em colchetes:
jsTry
// Parâmetros podem ser declarados numa variedade de formas sintáticas/*** @param {string} p1 - Um parâmetro do tipo string.* @param {string=} p2 - Um parâmetro opcional (sintaxe Closure)* @param {string} [p3] - Outro parâmetro opcional (sintaxe JSDoc).* @param {string} [p4="test"] - Um parâmetro opcional com um valor padrão* @return {string} Este é o resultado*/functionstringsStringStrings (p1 ,p2 ,p3 ,p4 ) {// TODO}
Da mesma forma para o retorno de uma função:
jsTry
/*** @return {PromiseLike<string>}*/functionps () {}/*** @returns {{ a: string, b: number }} - Pode ser usado '@returns' ou '@return'*/functionab () {}
@typedef
, @callback
, e @param
@typedef
pode ser usado para definir tipos complexos.
Uma sintaxe similar funciona para @param
jsTry
/*** @typedef {Object} SpecialType - cria um novo tipo chamado 'SpecialType'* @property {string} prop1 - uma propriedade string de SpecialType* @property {number} prop2 - uma propriedade numérica de SpecialType* @property {number=} prop3 - uma propriedade numérica opcional de SpecialType (sintaxe Closure)* @prop {number} [prop4] - uma propriedade numérica opcional de SpecialType (sintaxe JSDoc)* @prop {number} [prop5=42] - uma propriedade numérica opcional e com valor padrão de SpecialType*//** @type {SpecialType} */varspecialTypeObject ;specialTypeObject .prop3 ;
Na primeira linha, pode se usar tanto object
como Object
.
jsTry
/*** @typedef {object} SpecialType1 - cria um novo tipo chamado 'SpecialType'* @property {string} prop1 - uma propriedade string de SpecialType* @property {number} prop2 - uma propriedade numérica de SpecialType* @property {number=} prop3 - uma propriedade numérica opcional de SpecialType (sintaxe Closure)*//** @type {SpecialType1} */varspecialTypeObject1 ;
@param
permite uma sintaxe similar para especificações de tipo únicas.
Note que os nomes das propriedades aninhadas têm que serem prefixadas com o nome do parâmetro:
jsTry
/*** @param {Object} options - O mesmo objecto SpecialType acima* @param {string} options.prop1* @param {number} options.prop2* @param {number=} options.prop3* @param {number} [options.prop4]* @param {number} [options.prop5=42]*/functionspecial (options ) {return (options .prop4 || 1001) +options .prop5 ;}
@callback
é similar a @typedef
, mas especifica um tipo de uma função ao invés de um tipo de objeto:
jsTry
/*** @callback Predicate* @param {string} data* @param {number} [index]* @returns {boolean}*//** @type {Predicate} */constok = (s ) => !(s .length % 2);
E é claro, qualquer um desses tipos podem ser declarados usando a sintaxe Typescript em apenas uma linha de @typedef
:
js
/** @typedef {{ prop1: string, prop2: string, prop3?: number }} SpecialType *//** @typedef {(data: string, index?: number) => boolean} Predicate */
@template
Você pode declarar funções genéricas com a tag @template
:
jsTry
/*** @template T* @param {T} x - Um parâmetro genérico que flui até o tipo de retorno* @return {T}*/functionid (x ) {returnx ;}consta =id ("string");constb =id (123);constc =id ({});
Use vírgula ou múltiplas tags para declarar múltiplos parâmetros de tipo:
js
/*** @template T,U,V* @template W,X*/
Você também pode especificar uma restrição de tipo antes do nome do parâmetro. Apenas o primeiro parâmetro em uma lista sofre a restrição.
jsTry
/*** @template {string} K - K tem de ser do tipo string* @template {{ serious(): string }} Seriousalizable - tem de ter um método serious()* @param {K} key* @param {Seriousalizable} object*/functionseriousalize (key ,object ) {// ????}
Declarar classes ou tipos genéricos não é suportado.
Classes
Classes podem ser declaradas como Classes ES6.
jsTry
classC {/*** @param {number} data*/constructor(data ) {// Tipos de propriedades podem ser inferidosthis.name = "foo";// ou definidos explicitamente/** @type {string | null} */this.title = null;// ou simplesmente anotados, se a variável for preenchida mais tarde/** @type {number} */this.size ;this.initialize (data ); // Erro, initialize espera uma string como parâmetro}/*** @param {string} s*/initialize = function (s ) {this.size =s .length ;};}varc = newC (0);// C should only be called with new, but// because it is JavaScript, this is allowed and// considered an 'any'.varresult =C (1);
Ou elas podem também ser declaradas como funções construtoras, como descrito nan próxima seção:
@constructor
O compilador infere funções construtoras baseado nas atribuições da propriedade this, mas você pode fazer com que a checagem seja mais estrita e sugestões sejam melhores se você adicionar a tag @constructor
:
jsTry
/*** @constructor* @param {number} data*/functionC (data ) {// Tipos de propriedades podem ser inferidosthis.name = "foo";// ou definidos explicitamente/** @type {string | null} */this.title = null;// ou simplesmente anotados, se a variável for preenchida mais tarde/** @type {number} */this.size ;this.Argument of type 'number' is not assignable to parameter of type 'string'.2345Argument of type 'number' is not assignable to parameter of type 'string'.initialize (); data }/*** @param {string} s*/C .prototype .initialize = function (s ) {this.size =s .length ;};varc = newC (0);c .size ;varValue of type 'typeof C' is not callable. Did you mean to include 'new'?2348Value of type 'typeof C' is not callable. Did you mean to include 'new'?result =C (1);
Nota: Mensagens de erro só serão exibidas em bases de código JS com um JSConfig e
checkJs
habilitado.
Com @constructor
, o this
é checado dentro da função construtora C
, então você terá sugestões para o método initialize
e verá um erro se passar um número para ele. Seu editor pode exibir um warning se você apenas chamar C
ao invés de usá-lá como construtor.
Infelizmente, isso significa que funções construtoras que também podem ser chamadas não podem usar @constructor
.
@this
O compilador usualmente consegue inferir o tipo do this
quando tem algum contexto para isso. Quando ele não puder, você pode especificar explicitamente o tipo do this
com @this
:
jsTry
/*** @this {HTMLElement}* @param {*} e*/functioncallbackForLater (e ) {this.clientHeight =parseInt (e ); // Deve estar ok!}
@extends
Quando classes Javascript extendem uma classe base genérica, não há lugar para especificar o que o parâmetro de tipo deveria ser. A tag @extends
provém um lugar para aquele parâmetro de tipo:
jsTry
/*** @template T* @extends {Set<T>}*/classSortableSet extendsSet {// ...}
Note que @extends
funciona apenas com classes. Atualmente, não há forma para uma função construtora extender uma classe.
@enum
A tag @enum
permite que você crie um objeto literal cujos membros são todos de um tipo especificado. Diferentemente de outros objetos literais em Javascript, ela não permite outros membros.
jsTry
/** @enum {number} */constJSDocState = {BeginningOfLine : 0,SawAsterisk : 1,SavingComments : 2,};JSDocState .SawAsterisk ;
Note que a tag @enum
é bem diferente e mais simples que a enum
do TypeScript. Porém, diferentemente das enums do Typescript, @enum
pode ter qualquer tipo:
jsTry
/** @enum {function(number): number} */constMathFuncs = {add1 : (n ) =>n + 1,id : (n ) => -n ,sub1 : (n ) =>n - 1,};MathFuncs .add1 ;
Mais exemplos
jsTry
varsomeObj = {/*** @param {string} param1 - Documentos em atribuições de propriedades funcionam*/x : function (param1 ) {},};/*** Assim como documentos em atribuições de variáveis* @return {Window}*/letsomeFunc = function () {};/*** E métodos de classes* @param {string} greeting O cumprimento a ser usado*/Foo .prototype .sayHi = (greeting ) =>console .log ("Hi!");/*** E expressões de arrow functions* @param {number} x - Um multiplicador*/letmyArrow = (x ) =>x *x ;/*** O que significa que também funciona para componentes funcionais stateless em JSX também* @param {{a: string, b: number}} test - Algum parâmetro*/varsfc = (test ) => <div >{test .a .charAt (0)}</div >;/*** Um parâmetro pode ser um construtor de classe, usando sintaxe Closure.** @param {{new(...args: any[]): object}} C - A classe para ser registrada*/functionregisterClass (C ) {}/*** @param {...string} p1 - Um argumento 'rest' (vetor) de strings. (tratado como 'any')*/functionfn10 (p1 ) {}/*** @param {...string} p1 - Um argumento 'rest' (vetor) de strings. (tratado como 'any')*/functionfn9 (p1 ) {returnp1 .join ();}
Padrões que são conhecidos por NÃO serem suportados
Referir-se a objetos no espaço de valor como tipo não funciona a não ser que o objeto também crie um tipo, como uma função construtora.
jsTry
functionaNormalFunction () {}/*** @type {aNormalFunction}*/varwrong ;/*** Use 'typeof' ao invés da sintaxe anterior:* @type {typeof aNormalFunction}*/varright ;
Sinais de igual posteriores a um tipo de propriedade de um objeto literal não especifica uma propriedade opcional:
jsTry
/*** @type {{ a: string, b: number= }}*/varwrong ;/*** Use o ponto de interrogação como abaixo para especificar uma propriedade opcional* @type {{ a: string, b?: number }}*/varright ;
Tipos anuláveis só tem significado se a opção strictNullChecks
estiver habilitada:
jsTry
/*** @type {?number}* Com strictNullChecks: true -- number | null* Com strictNullChecks: false -- number*/varnullable ;
Você também pode usar uma união:
jsTry
/*** @type {number | null}* Com strictNullChecks: true -- number | null* Com strictNullChecks: false -- number*/varunionNullable ;
Tipos não-anuláveis não tem significado e são tratados apenas como seu tipo original:
jsTry
/*** @type {!number}* Tem apenas tipo number*/varnormal ;
Diferentemente de qualquer sistema de tipo JSDoc, Typescript permite apenas você marcar tipos contendo null ou não.
Não há não nulidade — se strictNullChecks está habilitada, então number
não é anulável.
Se está desabilitada, então number
é anulável.
Tags não suportadas
Typescript ignora qualquer tag JSDoc não suportada.
As tags seguintes têm issues abertas para serem suportadas:
@const
(issue #19672)@inheritdoc
(issue #23215)@memberof
(issue #7237)@yields
(issue #23857){@link …}
(issue #35524)
Extensões de Classes JS
Modificadores de propriedades JSDoc
From TypeScript 3.8 onwards, you can use JSDoc to modify the properties in a class. First are the accessibility modifiers: @public
, @private
, and @protected
.
Do Typescript 3.8 para frente, você pode usar JSDoc para modificar as propriedades em uma classe. Primeiramente, apresentamos os modificadores: @public
, @private
, and @protected
.
Essas tags funcionam exatamente como public
, private
, e protected
em Typescript, respectivamente.
jsTry
// @ts-checkclassCar {constructor() {/** @private */this.identifier = 100;}printIdentifier () {console .log (this.identifier );}}constc = newCar ();Property 'identifier' is private and only accessible within class 'Car'.2341Property 'identifier' is private and only accessible within class 'Car'.console .log (c .); identifier
@public
é sempre inferida e pode não ser especificada, mas significa que uma propriedade pode ser alcançada de qualquer lugar.@private
siginifica que a propriedade só pode ser usada dentro da classe que a contém.@protected
means that a property can only be used within the containing class, and all derived subclasses, but not on dissimilar instances of the containing class.@protected
siginifica que a propriedade só pode ser usada dentro da classe que a contém, e todas as subclasses derivadas, mas não em classes dissimilares da classe que a contém.
Depois, também adicionamos o modificador @readonly
para garantir que a propriedade só recebe uma atribuição durante a sua inicialização.
jsTry
// @ts-checkclassCar {constructor() {/** @readonly */this.identifier = 100;}printIdentifier () {console .log (this.identifier );}}constc = newCar ();console .log (c .identifier );