JSDoc: Надёжная альтернатива TypeScript

Источник: «JSDoc: A Solid Alternative To TypeScript»
Многие разработчики предпочитают использовать TypeScript из-за его функций проверки типов. Однако это требует дополнительного шага транспонирования, который может быть хлопотным и отнимающим время. В этой статье мы расскажем, как использовать JSDoc, чтобы получить все те же элементы контроля, но писать на обычном JavaScript, что позволяет сократить время разработки и улучшить документацию!

JavaScript закрепился в качестве одного из самых используемых скриптовых языков в последнее время. Он известен своей простотой в написании скриптов на веб-платформе. По мере развития языка он прошёл путь от "игрушечного" языка, использовавшего успех Java, до полноценного языка, используемого для создания не только небольших скриптов.

К сожалению, это выявляет недостатки языка. К ним относятся:

Typescript

В 2014 году компания Microsoft выпустила Typescript v1.0. Это изменило всю экосистему JavaScript.

TypeScript, который является надмножеством JavaScript, решил все вышеперечисленные проблемы и даже больше. Это делало его все более и более популярным даже в последнее время.

State of Js 2022 показывает повышение уровня использования TypeScript.

TypeScript, решив множество проблем, не обошёлся без недостатков.

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

Что такое JSDoc

JSDoc — это система документации для JavaScript, помогающая в работе с кодом JavaScript. Она работает с помощью комментариев, содержащих синтаксис JSDoc.

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

JSDoc vs Typescript

JSDoc и TypeScript решают проблемы с написанием и поддержкой обычного JavaScript-кода. Однако они используют разные подходы, имеющие свои преимущества и недостатки.

Преимущества JSDoc по сравнению с Typescript

Преимущества Typescript по сравнению с JSDoc

Хотя JSDoc имеет массу преимуществ перед TypeScript, есть причины, по которым использование Typescript со временем становится все более популярным. Вот некоторые из преимуществ Typescript по сравнению с JSDoc:

Как использовать JSDoc: Основы

Благодаря своей долговечности JSDoc имеет широкую поддержку во всех современных редакторах и может быть использован "из коробки" без установки.

Для добавления JSDoc в .js-файл, который, как заявлено, является просто комментарием, нужно открыть комментарий с дополнительным символом *.

// Нормальный Javascript Комментарий 1
/* Нормальный комментарий 2 */

/**
JSDoc, содержащий две звёздочки
*/

Вот несколько основных функций для начала работы.

Добавление описания кода к блоку кода

/** Название языка, для которого написан JSDoc*/
const language = "JavaScript"

Указание типов значений

/**
* Представляет автора этой статьи
* @type {string}
*/

const writerName = "Elijah"

Теперь указывается, что переменная username должна быть типа string.

Указание типа объектов и массивов

/**
* @type {Array<string>}
*/

const colours = ['red', 'blue', 'green']

/**
* @type {number[]}
*/

const primeNumbers = [1, 2, 3, 5, 7]

Оба метода допустимы в JSDoc (так же, как и в Typescript).

Указать тип объекта можно с помощью директивы @typedef.

/**
* * @typedef {Object} User - Схема User
* @property {number} id
* @property {string} username
* @property {string} email
* @property {Array<number>} postLikes
* @property {string[]} friends
*/
/**@type {User} */
const person1 = {
id: 847,
username: "Elijah",
email: "elijah@user.com",
postLikes: [44, 22, 24, 39],
friends: ['fede', 'Elijah']
}
/** @type {User} */
const person2 = {
id: 424,
username: "Winston",
email: "winston@user.com",
postLike: [18, 53, 98],
friends: ['Favour', 'Jane']
}

Типизация функций (параметры, возврат и ожидаемые типы ошибок)

/**
* Деление двух чисел.
* @param {number} dividend - Делимое.
* @param {number} divisor - Делитель.
* @returns {number} Результат деления.
*/

function divideNumbers(dividend, divisor) {
return dividend/divisor;
}

Ключевое слово @param, за которым следует определение типа, представляет собой значение, принимаемое определяемой функцией. Вы также можете добавить описание того, что представляет собой параметр, после дефиса (-).

Ключевое слово @returns используется для определения возвращаемого функцией результата. Это особенно полезно для больших функций. Может быть сложно просмотреть весь код, включая ранние возвраты, чтобы определить, что ожидается от функции.

Кроме того, вы можете добавить возможные ошибки, которые может выкинуть функция, используя директиву @throws.

Улучшив функцию деления, мы могли бы указать, что она возвращает ошибку, если делитель равен нулю, а также обработать это в самом коде.

/**
* Деление двух чисел.
* @param {number} dividend - Делимое.
* @param {number} divisor - Делитель.
* @returns {number} Результат деления.
* @throws {ZeroDivisionError} Аргумент делителя должен быть ненулевым
*/

function divideNumbers(dividend, divisor) {
if (divisor === 0) {
throw new DivisionByZeroError('Cannot Divide by zero')
}
return dividend/divisor;
}

@throws может принимать либо тип ошибки (ZeroDivisionError), либо описание (Argument divisor must...), либо оба.

/**
* Пользовательская ошибка при делении на ноль.
*/

class DivisionByZeroError extends Error {
constructor(message = "Cannot Divide By Zero") {
super(message);
this.name = "DivisionByZeroError";
}
}

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

Полная типизация классов (описание, конструктор и методы)

Если пойти ещё дальше, то можно также полностью типизировать синтаксис класса с помощью JSDoc.

/**
* Класс Rectangle
* @class
* @classdec Четырёхсторонний многоугольник с противоположными сторонами равной длины и четырьмя прямыми углами
*/

class Rectangle {
/**
* Инициализация объекта Rectangle.
* @param {number} length - Длина прямоугольника.
* @param {number} width - Ширина прямоугольника.
*/

constructor(length, width) {
this.length = length;
this.width = width;
}

/**
* Вычисление площади прямоугольника.
* @returns {number} Площадь прямоугольника.
*/

calculateArea() {
return this.length * this.width;
}

/**
* Вычисление периметра прямоугольника.
* @returns {number} Периметр прямоугольника.
*/

calculatePerimeter() {
return 2 * (this.length + this.width);
}
}

Выше представлен класс простого прямоугольника с двумя методами для вычисления его площади и периметра.

Ключевое слово @class используется, чтобы показать, что функция должна быть вызвана с помощью ключевого слова new. @classdec используется для описания всего класса. При типизации классов важно идти дальше, добавляя типы и описания к:

  1. Конструктору.
  2. Всем методам и переменным, созданным в классе.

Мы использовали ключевое слово @params, для указания типов и описания аргументов, которые необходимо передать в функцию конструктора. Методы в классе типизируются так же, как и функции, о чем мы говорили в предыдущем разделе.

Улучшение общей документации кода

Помимо добавления в код необходимых типов, существует множество способов, с помощью которых JSDoc помогает улучшить читабельность и простоту понимания. Вот несколько из них:

Конвертирование файлов JSDoc

Одним из самых больших плюсов использования JSDoc является возможность конвертировать файлы JSDoc для создания веб-сайта документации или даже в Typescript, чтобы воспользоваться преимуществами использования Typescript, такими как отлов ошибок во время компиляции, интеграция с проектами Typescript и т. д.

Генерирование веб-сайта документации из файлов JSDoc

Как было сказано выше, вы можете создать более читабельный GUI, выполнив следующие действия:

Установить jsdoc

npm install -g jsdoc

Запустите jsdoc для целевого файла

jsdoc path/to/file.js

Откройте сгенерированный сайт. В jsdoc CLI автоматически создаётся папка out, в которой хранятся файлы. Перейдите в папку out/index.html и откройте её в браузере.

Так выглядит сгенерированный по умолчанию шаблон jsdoc, но вы можете настроить его по-другому.
Так выглядит сгенерированный по умолчанию шаблон jsdoc, но вы можете настроить его по-другому.

Генерация .d.ts файлов из JSDoc

Файлы .d.ts в TypeScript представляют собой файлы деклараций, содержащие типы, доступные всем файлам .ts в проекте. Вы можете сгенерировать эти файлы из кода JSDoc, выполнив следующие действия:

Установите tsd-jsdoc в папку проекта

npm install tsd-jsdoc

Сгенерируйте .d.ts файлы

Для отдельного файла

jsdoc -t node_modules/tsd-jsdoc/dist -r our/jsdoc/file/path.js

Для нескольких файлов

jsdoc -t node_modules/tsd-jsdoc/dist -r file1.js file2.js file3.js ...

Для всей директории

jsdoc -t node_modules/tsd-jsdoc/dist -r src

Он объединяет все типы из файла(ов) в один файл out/types.d.ts.

Примечание: Здесь предполагается, что вы установили jsdoc из предыдущего раздела. Если нет, установите его перед выполнением этого шага.

Заключение

На данном этапе мы изучили основы использования JSDoc, а также генерацию типов и сайтов документации из JSDoc кода. JSDoc особенно полезен в тех случаях, когда время компиляции/шаг сборки Typescript оказывает негативное влияние на производительность. Он также полезен при работе с унаследованной кодовой базой.

Рич Харрис (Rich Harris, создатель Svelte и SvelteKit) перенёс весь репозиторий Svelte и SvelteKit с TypeScript на JSDoc. TypeScript также добавил поддержку многих деклараций JSDoc (источник)

Ресурсы

Дополнительные материалы

Предыдущая Статья

Основы TypeScript: ООП практика, классы и наследование

Следующая Статья

Основы TypeScript: Сетеры/Гетеры, protected, private/public/static