Добавьте аннотации JSDoc в файлы JavaScript

внешний интерфейс JavaScript
Добавьте аннотации JSDoc в файлы JavaScript

Поддерживаемый JSDoc

В следующем списке перечислены поддерживаемые в настоящее время аннотации JSDoc, которые можно использовать для добавления информации о типе в файлы JavaScript.

Обратите внимание, что в списке ниже нет тегов (например,@async) пока не поддерживаются.

  • @type
  • @param (or @arg or @argument)
  • @returns (or @return)
  • @typedef
  • @callback
  • @template
  • @class (or @constructor)
  • @this
  • @extends (or @augments)
  • @enum

Значения, которые они представляют, обычно совпадают со значениями, указанными выше на usejsdoc.org или их надмножестве. Код ниже описывает их различия и дает несколько примеров.

@type

можно использовать@typeОтмечайте имя типа и ссылайтесь на него (необработанный тип, тип, объявленный в TypeScript или в JSDoc).@typedefтег) может использовать любой тип TypeScript и большинство типов JSDoc.

/**
 * @type {string}
 */
var s;

/** @type {Window} */
var win;

/** @type {PromiseLike<string>} */
var promisedString;

// You can specify an HTML Element with DOM properties
/** @type {HTMLElement} */
var myElement = document.querySelector(selector);
element.dataset.myData = '';

@typeМожно указать типы объединения, например,stringа такжеbooleanтип союза.

/**
 * @type {(string | boolean)}
 */
var sb;

Обратите внимание, что скобки необязательны.

/**
 * @type {string | boolean}
 */
var sb;

Существует несколько способов указать типы массивов:

/** @type {number[]} */
var ns;
/** @type {Array.<number>} */
var nds;
/** @type {Array<number>} */
var nas;

Вы также можете указать тип литерала объекта. Например, сa(строка) иb(числовое) свойство объекта, используя следующий синтаксис:

/** @type {{ a: string, b: number }} */
var var9;

Может быть указан с использованием строковых и числовых подписей индексаmap-likeа такжеarray-likeобъекта, используя стандартный синтаксис JSDoc или синтаксис TypeScript.

/**
 * A map-like object that maps arbitrary `string` properties to `number`s.
 *
 * @type {Object.<string, number>}
 */
var stringToNumber;

/** @type {Object.<number, object>} */
var arrayLike;

Эти два типа такие же, как в TypeScript.{ [x: string]: number }а также{ [x: number]: any }эквивалентны. Компилятор распознает оба синтаксиса.

Типы функций могут быть указаны с использованием синтаксиса TypeScript или Closure.

/** @type {function(string, boolean): number} Closure syntax */
var sbn;
/** @type {(s: string, b: boolean) => number} Typescript syntax */
var sbn2;

или напрямую использовать неуказанныйFunctionТипы:

/** @type {Function} */
var fn7;
/** @type {function} */
var fn6;

Также могут использоваться другие типы закрытия:

/**
 * @type {*} - can be 'any' type
 */
var star;
/**
 * @type {?} - unknown type (same as 'any')
 */
var question;

конвертировать

TypeScript заимствует синтаксис преобразования из Closure. использовать перед выражением в скобках@typeФлаги, которые могут преобразовывать один тип в другой

/**
 * @type {number | string}
 */
var numberOrString = Math.random() < 0.5 ? "hello" : 100;
var typeAssertedNumber = /** @type {number} */ (numberOrString)

тип импорта

Объявления можно импортировать из других файлов, используя типы импорта. Этот синтаксис специфичен для TypeScript и отличается от стандарта JSDoc:

/**
 * @param p { import("./a").Pet }
 */
function walk(p) {
    console.log(`Walking ${p.name}...`);
}

Импортированные типы также можно использовать в объявлениях псевдонимов типов:

/**
 * @typedef { import("./a").Pet } Pet
 */

/**
 * @type {Pet}
 */
var myPet;
myPet.name;

Импортированные типы можно использовать для типов, которые получают значение из модуля.

/**
 * @type {typeof import("./a").x }
 */
var x = require("./a").x;

@paramа также@returns

@paramграмматика и@typeТо же самое, но с дополнительным именем параметра. использовать[]Параметры могут быть объявлены необязательными:

// Parameters may be declared in a variety of syntactic forms
/**
 * @param {string}  p1 - A string param.
 * @param {string=} p2 - An optional param (Closure syntax)
 * @param {string} [p3] - Another optional param (JSDoc syntax).
 * @param {string} [p4="test"] - An optional param with a default value
 * @return {string} This is the result
 */
function stringsStringStrings(p1, p2, p3, p4){
  // TODO
}

Тип возвращаемого значения функции аналогичен:

/**
 * @return {PromiseLike<string>}
 */
function ps(){}

/**
 * @returns {{ a: string, b: number }} - May use '@returns' as well as '@return'
 */
function ab(){}

@typedef, @callback, а также@param

@typedefМожет использоваться для объявления сложных типов. а также@paramаналогичный синтаксис.

/**
 * @typedef {Object} SpecialType - creates a new type named 'SpecialType'
 * @property {string} prop1 - a string property of SpecialType
 * @property {number} prop2 - a number property of SpecialType
 * @property {number=} prop3 - an optional number property of SpecialType
 * @prop {number} [prop4] - an optional number property of SpecialType
 * @prop {number} [prop5=42] - an optional number property of SpecialType with default
 */
/** @type {SpecialType} */
var specialTypeObject;

можно использовать в первой строкеobjectилиObject.

/**
 * @typedef {object} SpecialType1 - creates a new type named 'SpecialType1'
 * @property {string} prop1 - a string property of SpecialType1
 * @property {number} prop2 - a number property of SpecialType1
 * @property {number=} prop3 - an optional number property of SpecialType1
 */
/** @type {SpecialType1} */
var specialTypeObject1;

@paramДопускается аналогичный синтаксис. Обратите внимание, что имена вложенных свойств должны начинаться с имени параметра:

/**
 * @param {Object} options - The shape is the same as SpecialType above
 * @param {string} options.prop1
 * @param {number} options.prop2
 * @param {number=} options.prop3
 * @param {number} [options.prop4]
 * @param {number} [options.prop5=42]
 */
function special(options) {
  return (options.prop4 || 1001) + options.prop5;
}

@callbackа также@typedefАналогично, но указывает тип функции вместо типа объекта:

/**
 * @callback Predicate
 * @param {string} data
 * @param {number} [index]
 * @returns {boolean}
 */
/** @type {Predicate} */
const ok = s => !(s.length % 2);

Конечно, все эти типы могут использовать синтаксис TypeScript.@typedefОбъявите в одной строке:

/** @typedef {{ prop1: string, prop2: string, prop3?: number }} SpecialType */
/** @typedef {(data: string, index?: number) => boolean} Predicate */

@template

использовать@templateОбъявить дженерики:

/**
 * @template T
 * @param {T} x - A generic parameter that flows through to the return type
 * @return {T}
 */
function id(x){ return x }

Объявите несколько параметров типа с запятыми или несколькими токенами:

/**
 * @template T,U,V
 * @template W,X
 */

Ограничения типа также могут быть указаны перед именем параметра. Только первый параметр типа списка будет ограничен:

/**
 * @template {string} K - K must be a string or string literal
 * @template {{ serious(): string }} Seriousalizable - must have a serious method
 * @param {K} key
 * @param {Seriousalizable} object
 */
function seriousalize(key, object) {
  // ????
}

@constructor

Компилятор проходитthisНазначение свойств для вывода конструктора, но можно сделать проверку строже, подсказку дружелюбнее, можно добавить@constructorотметка:

/**
 * @constructor
 * @param {number} data
 */
function C(data) {
  this.size = 0;
  this.initialize(data); // Should error, initializer expects a string
}
/**
 * @param {string} s
 */
C.prototype.initialize = function (s) {
  this.size = s.length
}

var c = new C(0);
var result = C(1); // C should only be called with new

пройти через@constructor,thisбудет в конструктореCпроверено, так что вы находитесь вinitializeметод, и если вы передадите число, вы также получите сообщение об ошибке. Если вы позвоните напрямуюCвместо его построения вы также получите ошибку.

К сожалению, это означает, что конструкторы, которые могут создаваться и вызываться напрямую, не могут быть использованы.@constructor.

@this

Компилятор обычно может сделать вывод из контекстаthisтип. но вы можете использовать@thisчтобы явно указать его тип:

/**
 * @this {HTMLElement}
 * @param {*} e
 */
function callbackForLater(e) {
    this.clientHeight = parseInt(e) // should be fine!
}

@extends

Когда класс JavaScript расширяет базовый класс, негде указать тип параметра типа. а также@extendsМаркеры обеспечивают такой способ:

/**
 * @template T
 * @extends {Set<T>}
 */
class SortableSet extends Set {
  // ...
}

Уведомление@extendsДействует только на классы. В настоящее время конструктор не может быть реализован.

@enum

@enumТеги позволяют создать литерал объекта, члены которого относятся к определенному типу. В отличие от большинства литералов объектов в JavaScript, он не позволяет добавлять дополнительные элементы.

/** @enum {number} */
const JSDocState = {
  BeginningOfLine: 0,
  SawAsterisk: 1,
  SavingComments: 2,
}

Уведомление@enumс помощью машинописного текста@enumСовсем другое, это проще. Однако, в отличие от перечислений TypeScript,@enumМожет быть любого типа:

/** @enum {function(number): number} */
const Math = {
  add1: n => n + 1,
  id: n => -n,
  sub1: n => n - 1,
}

больше примеров

var someObj = {
  /**
   * @param {string} param1 - Docs on property assignments work
   */
  x: function(param1){}
};

/**
 * As do docs on variable assignments
 * @return {Window}
 */
let someFunc = function(){};

/**
 * And class methods
 * @param {string} greeting The greeting to use
 */
Foo.prototype.sayHi = (greeting) => console.log("Hi!");

/**
 * And arrow functions expressions
 * @param {number} x - A multiplier
 */
let myArrow = x => x * x;

/**
 * Which means it works for stateless function components in JSX too
 * @param {{a: string, b: number}} test - Some param
 */
var fc = (test) => <div>{test.a.charAt(0)}</div>;

/**
 * A parameter can be a class constructor, using Closure syntax.
 *
 * @param {{new(...args: any[]): object}} C - The class to register
 */
function registerClass(C) {}

/**
 * @param {...string} p1 - A 'rest' arg (array) of strings. (treated as 'any')
 */
function fn10(p1){}

/**
 * @param {...string} p1 - A 'rest' arg (array) of strings. (treated as 'any')
 */
function fn9(p1) {
  return p1.join();
}

известный неподдерживаемый режим

Невозможно рассматривать объект как тип в пространстве значений, если только объект не создает тип, например конструктор.

function aNormalFunction() {

}
/**
 * @type {aNormalFunction}
 */
var wrong;
/**
 * Use 'typeof' instead:
 * @type {typeof aNormalFunction}
 */
var right;

на литеральные свойства объекта=Суффикс указать нельзя. Этот атрибут является необязательным:

/**
 * @type {{ a: string, b: number= }}
 */
var wrong;
/**
 * Use postfix question on the property name instead:
 * @type {{ a: string, b?: number }}
 */
var right;

Nullableпечатать только при включенииstrictNullChecksЭто работает только при проверке:

/**
 * @type {?number}
 * With strictNullChecks: true -- number | null
 * With strictNullChecks: off  -- number
 */
var nullable;

Non-nullableТипы не имеют смысла, рассматриваются как их исходный тип:

/**
 * @type {!number}
 * Just has type number
 */
var normal;

В отличие от системы типов JSDoc, TypeScript позволяет помечать типы только как исключенные из пакетов.null. не чистоNon-nullable-- если включеноstrictNullChecks,Такnumberправильно и неправильноnullиз. Если не включено, тоnumberвозможно дляnullиз.