1 added
1 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Это перевод статьи JavaScript Type Linting, написанной Робертом Биггсом. Повествование ведётся от имени автора оригинала.</p>
1
<p>Это перевод статьи JavaScript Type Linting, написанной Робертом Биггсом. Повествование ведётся от имени автора оригинала.</p>
2
<p>Существует распространённое заблуждение: якобы единственный способ избежать ошибок типизации в JavaScript - писать код на языке со статической типизацией, который компилируется в JavaScript. С этой целью используют ClojureScript, Elm, ReasonML, TypeScript и так далее. В настоящее время самое популярное решение - TypeScript.</p>
2
<p>Существует распространённое заблуждение: якобы единственный способ избежать ошибок типизации в JavaScript - писать код на языке со статической типизацией, который компилируется в JavaScript. С этой целью используют ClojureScript, Elm, ReasonML, TypeScript и так далее. В настоящее время самое популярное решение - TypeScript.</p>
3
<p>На самом деле существует альтернативный способ борьбы с ошибками типизации - проверка или линтинг типов. Он реализуется с помощью Visual Studio Code и сервера TypeScript, который работает в фоновом режиме. Когда вы пишете на JavaScript, TypeScript анализирует типы данных и сообщает об ошибках. Это происходит в режиме реального времени, поэтому нет нужды выполнять сборку - типы проверяются автоматически, когда вы вводите код. Что ещё важнее, вы пишете на JavaScript, а не на TypeScript. Есть три способа проверки типов в Visual Studio Code:</p>
3
<p>На самом деле существует альтернативный способ борьбы с ошибками типизации - проверка или линтинг типов. Он реализуется с помощью Visual Studio Code и сервера TypeScript, который работает в фоновом режиме. Когда вы пишете на JavaScript, TypeScript анализирует типы данных и сообщает об ошибках. Это происходит в режиме реального времени, поэтому нет нужды выполнять сборку - типы проверяются автоматически, когда вы вводите код. Что ещё важнее, вы пишете на JavaScript, а не на TypeScript. Есть три способа проверки типов в Visual Studio Code:</p>
4
<ol><li>На уровне файла.</li>
4
<ol><li>На уровне файла.</li>
5
<li>Глобально для всех проектов.</li>
5
<li>Глобально для всех проектов.</li>
6
<li>Только для конкретного проекта.</li>
6
<li>Только для конкретного проекта.</li>
7
</ol><h2>Содержание</h2>
7
</ol><h2>Содержание</h2>
8
<ul><li><a>Как настроить проверку типов</a></li>
8
<ul><li><a>Как настроить проверку типов</a></li>
9
<li><a>Вывод типов</a></li>
9
<li><a>Вывод типов</a></li>
10
<li><a>Указание типов в комментариях JSDoc</a></li>
10
<li><a>Указание типов в комментариях JSDoc</a></li>
11
<li><a>Примеры типобезопасного JavaScript</a></li>
11
<li><a>Примеры типобезопасного JavaScript</a></li>
12
<li><a>Как определять типы JavaScript</a></li>
12
<li><a>Как определять типы JavaScript</a></li>
13
<li><a>Пользовательские типы</a></li>
13
<li><a>Пользовательские типы</a></li>
14
<li><a>Импорт типов</a></li>
14
<li><a>Импорт типов</a></li>
15
<li><a>Необязательные типы</a></li>
15
<li><a>Необязательные типы</a></li>
16
<li><a>Union Types (объединение типов)</a></li>
16
<li><a>Union Types (объединение типов)</a></li>
17
<li><a>Приведение типов</a></li>
17
<li><a>Приведение типов</a></li>
18
<li><a>Пропуск строки</a></li>
18
<li><a>Пропуск строки</a></li>
19
<li><a>Уменьшаем объём комментариев JSDoc</a></li>
19
<li><a>Уменьшаем объём комментариев JSDoc</a></li>
20
<li><a>Как настроить проект</a></li>
20
<li><a>Как настроить проект</a></li>
21
<li><a>Пакетный импорт</a></li>
21
<li><a>Пакетный импорт</a></li>
22
<li><a>Примеры</a></li>
22
<li><a>Примеры</a></li>
23
</ul><h2>Как настроить проверку типов</h2>
23
</ul><h2>Как настроить проверку типов</h2>
24
<p>Как отмечалось выше, это можно сделать на уровне файла, глобально для всех проектов и для отдельного проекта. Рассмотрим эти способы подробнее.</p>
24
<p>Как отмечалось выше, это можно сделать на уровне файла, глобально для всех проектов и для отдельного проекта. Рассмотрим эти способы подробнее.</p>
25
<h3>Проверка типов на уровне файла</h3>
25
<h3>Проверка типов на уровне файла</h3>
26
<p>Если вы работаете в Visual Studio Code, линтинг типов можно включить несколькими способами. Самый простой - добавить в начале файла такой комментарий:</p>
26
<p>Если вы работаете в Visual Studio Code, линтинг типов можно включить несколькими способами. Самый простой - добавить в начале файла такой комментарий:</p>
27
<h3>Проверка типов для всех проектов</h3>
27
<h3>Проверка типов для всех проектов</h3>
28
<p>Если не хотите каждый раз добавлять комментарии в файлы, включите проверку в редакторе. Найдите в настройках пункт Check JS и отметьте его галочкой.</p>
28
<p>Если не хотите каждый раз добавлять комментарии в файлы, включите проверку в редакторе. Найдите в настройках пункт Check JS и отметьте его галочкой.</p>
29
<p>Так вы включаете линтинг типов для любого файла с кодом JavaScript, который редактируете.</p>
29
<p>Так вы включаете линтинг типов для любого файла с кодом JavaScript, который редактируете.</p>
30
<h3>Проверка типов для конкретного проекта</h3>
30
<h3>Проверка типов для конкретного проекта</h3>
31
<p>Если не хотите включать проверку типов для всех проектов по умолчанию, ограничьтесь конкретным проектом. Соответствующие настройки надо указать в файле settings.json. Сначала создайте директорию .vscode в корне проекта. В этой директории создайте файл settings.json, в котором включите проверку типов:</p>
31
<p>Если не хотите включать проверку типов для всех проектов по умолчанию, ограничьтесь конкретным проектом. Соответствующие настройки надо указать в файле settings.json. Сначала создайте директорию .vscode в корне проекта. В этой директории создайте файл settings.json, в котором включите проверку типов:</p>
32
<p>Третий способ предпочтительный, так как с его помощью можно включить линтинг типов во всех файлах JavaScript в выбранном проекте. Чтобы отключить проверку типов в каком-либо файле, например, в файлах, созданных Gulp или другими сборщиками, просто добавьте в начале файла комментарий:</p>
32
<p>Третий способ предпочтительный, так как с его помощью можно включить линтинг типов во всех файлах JavaScript в выбранном проекте. Чтобы отключить проверку типов в каком-либо файле, например, в файлах, созданных Gulp или другими сборщиками, просто добавьте в начале файла комментарий:</p>
33
<h2>Вывод типов</h2>
33
<h2>Вывод типов</h2>
34
<p>Если вы включили проверку типов одним из указанных выше способов, Visual Studio Code с помощью сервера TypeScript парсит файлы JavaScript и определяет используемые типы данных. По умолчанию это происходит с помощью вывода типов (Type Inference). Это значит, что если вы объявляете переменную или константу для строки или числа, для этой переменной будет определён соответствующий тип данных.</p>
34
<p>Если вы включили проверку типов одним из указанных выше способов, Visual Studio Code с помощью сервера TypeScript парсит файлы JavaScript и определяет используемые типы данных. По умолчанию это происходит с помощью вывода типов (Type Inference). Это значит, что если вы объявляете переменную или константу для строки или числа, для этой переменной будет определён соответствующий тип данных.</p>
35
<p>Многие языки программирования со строгой типизацией используют вывод типов в качестве быстрого способа определения типов. TypeScript тоже поддерживает такой подход. Но это не лучший способ, так как если TypeScript точно не определяет тип данных, он использует any. Это плохо, так как если типы сводятся к any, это делает бессмысленной их проверку.</p>
35
<p>Многие языки программирования со строгой типизацией используют вывод типов в качестве быстрого способа определения типов. TypeScript тоже поддерживает такой подход. Но это не лучший способ, так как если TypeScript точно не определяет тип данных, он использует any. Это плохо, так как если типы сводятся к any, это делает бессмысленной их проверку.</p>
36
<h2>Указание типов в комментариях JSDoc</h2>
36
<h2>Указание типов в комментариях JSDoc</h2>
37
<p>Вы можете указывать типы данных для TypeScript в коде JavaScript с помощью комментариев JSDoc. Они представляют собой валидные комментарии JavaScript, не влияют на выполнение кода и не требуют компиляции. JavaScript с комментариями JSDoc можно запускать в браузере или на Node.js.</p>
37
<p>Вы можете указывать типы данных для TypeScript в коде JavaScript с помощью комментариев JSDoc. Они представляют собой валидные комментарии JavaScript, не влияют на выполнение кода и не требуют компиляции. JavaScript с комментариями JSDoc можно запускать в браузере или на Node.js.</p>
38
<p>Этот подход обеспечивает такие же возможности, как TypeScript - удобные автодополнения и уведомления о некорректном использовании типов. Если вы передадите в функцию некорректный аргумент, Visual Studio Code сразу уведомит вас. Так же происходит при использовании TypeScript. Благодаря этому можно не использовать файлы d.ts, так как комментарии с указанием типов можно писать в JavaScript.</p>
38
<p>Этот подход обеспечивает такие же возможности, как TypeScript - удобные автодополнения и уведомления о некорректном использовании типов. Если вы передадите в функцию некорректный аргумент, Visual Studio Code сразу уведомит вас. Так же происходит при использовании TypeScript. Благодаря этому можно не использовать файлы d.ts, так как комментарии с указанием типов можно писать в JavaScript.</p>
39
<p>JSDoc предназначен для документирования JavaScript. Кажется, этот инструмент работает лучше подхода с использованием TypeScript и аннотаций типов, интерфейсов и других структур, которых нет в JavaScript. В TypeScript реализованы паттерны, характерные для C# и Java, поэтому он не похож на JavaScript. Скорее, он похож на C# и Java. Если вам нравятся эти языки, вероятно, вам понравится и сам TypeScript. В свою очередь, JSDoc не влияет на то, как выглядит JavaScript. Вы просто пишете обычный код JavaScript с комментариями, в которых определяются типы, использованные в коде.</p>
39
<p>JSDoc предназначен для документирования JavaScript. Кажется, этот инструмент работает лучше подхода с использованием TypeScript и аннотаций типов, интерфейсов и других структур, которых нет в JavaScript. В TypeScript реализованы паттерны, характерные для C# и Java, поэтому он не похож на JavaScript. Скорее, он похож на C# и Java. Если вам нравятся эти языки, вероятно, вам понравится и сам TypeScript. В свою очередь, JSDoc не влияет на то, как выглядит JavaScript. Вы просто пишете обычный код JavaScript с комментариями, в которых определяются типы, использованные в коде.</p>
40
<p>TypeScript - язык, который компилируется в JavaScript. Он обеспечивает безопасность типов до сборки кода. После сборки у вас остаётся чистый JavaScript. Всё, что делает TypeScript, оказывается бесполезным, как только вы запускаете код JavaScript в браузере или Node.js. Поэтому единственной гарантией корректного использования типов при выполнении кода JavaScript остаются защитников типов (type guards). Если переживаете, что ошибки типизации сломают код, можете использовать type guards. Статическая типизация не гарантирует отсутствия ошибок при выполнении кода.</p>
40
<p>TypeScript - язык, который компилируется в JavaScript. Он обеспечивает безопасность типов до сборки кода. После сборки у вас остаётся чистый JavaScript. Всё, что делает TypeScript, оказывается бесполезным, как только вы запускаете код JavaScript в браузере или Node.js. Поэтому единственной гарантией корректного использования типов при выполнении кода JavaScript остаются защитников типов (type guards). Если переживаете, что ошибки типизации сломают код, можете использовать type guards. Статическая типизация не гарантирует отсутствия ошибок при выполнении кода.</p>
41
<p>С другой стороны, информация о типах в JSDoc - это валидные комментарии JavaScript. Если хотите, можете оставлять их в коде - они не влияют на его выполнение. Но в целом надо стремиться минимизировать код, а это предполагает отказ от комментариев.</p>
41
<p>С другой стороны, информация о типах в JSDoc - это валидные комментарии JavaScript. Если хотите, можете оставлять их в коде - они не влияют на его выполнение. Но в целом надо стремиться минимизировать код, а это предполагает отказ от комментариев.</p>
42
<blockquote><h3>Также полезно</h3>
42
<blockquote><h3>Также полезно</h3>
43
<p><a>Что такое __dirname в JavaScript</a>.</p>
43
<p><a>Что такое __dirname в JavaScript</a>.</p>
44
</blockquote><h2>Примеры типобезопасного JavaScript</h2>
44
</blockquote><h2>Примеры типобезопасного JavaScript</h2>
45
<p>Чтобы показать, как выглядит типобезопасный JavaScript с комментариями JSDoc, я использовал npm-пакет @composi/core. Он написан с использованием ECMAScript 2015. В нём не используется файл d.ts, а информация о типах передаётся через комментарии JSDoc. Если импортировать этот модуль в проект, вся информация о типах становится доступной конечному пользователю.</p>
45
<p>Чтобы показать, как выглядит типобезопасный JavaScript с комментариями JSDoc, я использовал npm-пакет @composi/core. Он написан с использованием ECMAScript 2015. В нём не используется файл d.ts, а информация о типах передаётся через комментарии JSDoc. Если импортировать этот модуль в проект, вся информация о типах становится доступной конечному пользователю.</p>
46
<p>На иллюстрации ниже можно увидеть функции, импортированные из @composi/core. Если навести курсор на функцию h, появляется всплывающая подсказка с ожидаемыми аргументами и их типами.</p>
46
<p>На иллюстрации ниже можно увидеть функции, импортированные из @composi/core. Если навести курсор на функцию h, появляется всплывающая подсказка с ожидаемыми аргументами и их типами.</p>
47
<p>На следующей иллюстрации видно, что происходит при наведении курсора на функцию render. На всплывающей подсказке появляются ожидаемые параметры и их типы. Обратите внимание, что VNode и container - обязательные параметры, а hydrateThis - опциональный параметр.</p>
47
<p>На следующей иллюстрации видно, что происходит при наведении курсора на функцию render. На всплывающей подсказке появляются ожидаемые параметры и их типы. Обратите внимание, что VNode и container - обязательные параметры, а hydrateThis - опциональный параметр.</p>
48
<p>На следующей иллюстрации видно, что происходит, если передать в функцию render некорректные аргументы. Всплывающая подсказка информирует, что мы не передали обязательный аргумент container. Также мы видим два варианта быстрого исправления ошибки. Заметьте, что в верхней части всплывающей подсказки есть явное сообщение о том, что функция ожидает два или три аргумента, а мы передали в неё только один аргумент.</p>
48
<p>На следующей иллюстрации видно, что происходит, если передать в функцию render некорректные аргументы. Всплывающая подсказка информирует, что мы не передали обязательный аргумент container. Также мы видим два варианта быстрого исправления ошибки. Заметьте, что в верхней части всплывающей подсказки есть явное сообщение о том, что функция ожидает два или три аргумента, а мы передали в неё только один аргумент.</p>
49
<p>Также заметьте, что в подсказке есть название файла в исходном коде, номер строки кода и номер символа, в которых определяется, что функция должна получить обязательный аргумент container.</p>
49
<p>Также заметьте, что в подсказке есть название файла в исходном коде, номер строки кода и номер символа, в которых определяется, что функция должна получить обязательный аргумент container.</p>
50
<p>На следующей иллюстрации показано, что происходит после нажатия Peek Problem.</p>
50
<p>На следующей иллюстрации показано, что происходит после нажатия Peek Problem.</p>
51
<p>Если нажать на название файла, Visual Studio Code перебрасывает нас в исходный код импортированного модуля и показывает параметры функции render.</p>
51
<p>Если нажать на название файла, Visual Studio Code перебрасывает нас в исходный код импортированного модуля и показывает параметры функции render.</p>
52
<p>Далее мы передаём в функцию второй аргумент. Предупреждение меняется - появляется сообщение, что число 123 - это невалидный аргумент, так как функция render ожидает первым аргумент с типом VNode.</p>
52
<p>Далее мы передаём в функцию второй аргумент. Предупреждение меняется - появляется сообщение, что число 123 - это невалидный аргумент, так как функция render ожидает первым аргумент с типом VNode.</p>
53
<p>На следующей иллюстрации видно, что мы исправляем ошибку и передаём в функцию подходящий аргумент. Теперь появляются проблемы со вторым аргументом - функция ожидает другой тип данных.</p>
53
<p>На следующей иллюстрации видно, что мы исправляем ошибку и передаём в функцию подходящий аргумент. Теперь появляются проблемы со вторым аргументом - функция ожидает другой тип данных.</p>
54
<p>Как видно из примеров выше, можно пользоваться типобезопасным JavaScript без необходимости компилировать в JavaScript код, написанный на языке с поддержкой статической типизации. Это происходит благодаря проверке типов, которую обеспечивают Visual Studio Code и TypeScript. Да, мы используем TypeScript, но он работает в фоне и выступает в качестве линтера типов. Мы всё время пишем на чистом JavaScript, а не на TypeScript. Но TypeScript понимает типы данных, которые мы используем в JavaScript, благодаря комментариям JSDoc.</p>
54
<p>Как видно из примеров выше, можно пользоваться типобезопасным JavaScript без необходимости компилировать в JavaScript код, написанный на языке с поддержкой статической типизации. Это происходит благодаря проверке типов, которую обеспечивают Visual Studio Code и TypeScript. Да, мы используем TypeScript, но он работает в фоне и выступает в качестве линтера типов. Мы всё время пишем на чистом JavaScript, а не на TypeScript. Но TypeScript понимает типы данных, которые мы используем в JavaScript, благодаря комментариям JSDoc.</p>
55
<p>Я верю, что использование комментариев JSDoc - очень важная находка для экосистемы JavaScript, так как она обеспечивает типобезопасность без необходимости писать код на TypeScript или другом языке со статической типизацией с последующей компиляцией в JavaScript.</p>
55
<p>Я верю, что использование комментариев JSDoc - очень важная находка для экосистемы JavaScript, так как она обеспечивает типобезопасность без необходимости писать код на TypeScript или другом языке со статической типизацией с последующей компиляцией в JavaScript.</p>
56
<h2>Как определять типы JavaScript</h2>
56
<h2>Как определять типы JavaScript</h2>
57
<p>С помощью JSDoc можно документировать типы данных, которые используются в вашем JavaScript-коде. В отличие от других решений, которые добавляют искусственную систему типов в JavaScript, JSDoc работает с типами данных самого JavaScript. В JavaScript слабая типизация, а типы присваиваются данным в момент выполнения кода. Суть динамической типизации в JavaScript можно объяснить термином "утиная типизация" - если что-то ходит как утка и крякает как утка, это и есть утка. Это значит, что если два абсолютно разных объекта имеют одинаковые свойства, их можно использовать как взаимозаменяемые, если вы используете только общие свойства. В JavaScript это часто реализуется с помощью доступа к свойству родительского объекта через его цепочку прототипов. Полный список типов, которые можно определить с помощью JSDoc,<a>указан в документации</a>. Ниже идёт краткое описание.</p>
57
<p>С помощью JSDoc можно документировать типы данных, которые используются в вашем JavaScript-коде. В отличие от других решений, которые добавляют искусственную систему типов в JavaScript, JSDoc работает с типами данных самого JavaScript. В JavaScript слабая типизация, а типы присваиваются данным в момент выполнения кода. Суть динамической типизации в JavaScript можно объяснить термином "утиная типизация" - если что-то ходит как утка и крякает как утка, это и есть утка. Это значит, что если два абсолютно разных объекта имеют одинаковые свойства, их можно использовать как взаимозаменяемые, если вы используете только общие свойства. В JavaScript это часто реализуется с помощью доступа к свойству родительского объекта через его цепочку прототипов. Полный список типов, которые можно определить с помощью JSDoc,<a>указан в документации</a>. Ниже идёт краткое описание.</p>
58
<h3>Примитивные типы vs. объекты</h3>
58
<h3>Примитивные типы vs. объекты</h3>
59
<p>В JavaScript есть следующие примитивные типы данных:</p>
59
<p>В JavaScript есть следующие примитивные типы данных:</p>
60
<ul><li>undefined</li>
60
<ul><li>undefined</li>
61
<li>null</li>
61
<li>null</li>
62
<li>boolean</li>
62
<li>boolean</li>
63
<li>число</li>
63
<li>число</li>
64
<li>строка</li>
64
<li>строка</li>
65
</ul><p>Примитивные типы в JavaScript неизменяемые. Они сравниваются по значению. Все сложные типы - объекты. Они изменяемые и сравниваются по ссылке. У примитивных типов строка и число есть конструкторы - глобальные объекты String и Number. Другие структуры данных, включая массивы, объекты, функции и классы - относятся к типу данных объект.</p>
65
</ul><p>Примитивные типы в JavaScript неизменяемые. Они сравниваются по значению. Все сложные типы - объекты. Они изменяемые и сравниваются по ссылке. У примитивных типов строка и число есть конструкторы - глобальные объекты String и Number. Другие структуры данных, включая массивы, объекты, функции и классы - относятся к типу данных объект.</p>
66
<h3>Базовые типы</h3>
66
<h3>Базовые типы</h3>
67
<p>JSDoc - соглашение об использовании стандартных комментариев JavaScript. Обычно комментарии используются в следующем формате:</p>
67
<p>JSDoc - соглашение об использовании стандартных комментариев JavaScript. Обычно комментарии используются в следующем формате:</p>
68
<p>С помощью специальных терминов и форматов внутри этих комментариев определяются типы JavaScript.</p>
68
<p>С помощью специальных терминов и форматов внутри этих комментариев определяются типы JavaScript.</p>
69
<h3>@type{}</h3>
69
<h3>@type{}</h3>
70
<p>Самый важный тег JSDoc - @type, за которым следуют фигурные скобки {}. Когда вы определяете тип, он всегда заключается в фигурные скобки.</p>
70
<p>Самый важный тег JSDoc - @type, за которым следуют фигурные скобки {}. Когда вы определяете тип, он всегда заключается в фигурные скобки.</p>
71
<p>Аналогично можно указать тип для переменной sum в примере ниже.</p>
71
<p>Аналогично можно указать тип для переменной sum в примере ниже.</p>
72
<p>Типы данных в комментариях JSDoc можно писать с прописной или строчной буквы. Согласно текущему соглашению, предпочтительнее писать названия типов со строчной буквы.</p>
72
<p>Типы данных в комментариях JSDoc можно писать с прописной или строчной буквы. Согласно текущему соглашению, предпочтительнее писать названия типов со строчной буквы.</p>
73
<h3>Тип any</h3>
73
<h3>Тип any</h3>
74
<p>Как отмечалось выше, когда TypeScript не может определить тип данных, он присваивает им тип any. Он не входит в число валидных типов данных JavaScript. Так TypeScript помечает данные, тип которых не надо проверять. Вы также можете вручную пометить данные типом any. Зачем это нужно? Вероятно, это полезно в редких случаях, когда вы не уверены, какой тип данных должен использоваться. Это связано со случайным приведением типов, которое может выполнить JavaScript. Тип any можно обозначить несколькими способами.</p>
74
<p>Как отмечалось выше, когда TypeScript не может определить тип данных, он присваивает им тип any. Он не входит в число валидных типов данных JavaScript. Так TypeScript помечает данные, тип которых не надо проверять. Вы также можете вручную пометить данные типом any. Зачем это нужно? Вероятно, это полезно в редких случаях, когда вы не уверены, какой тип данных должен использоваться. Это связано со случайным приведением типов, которое может выполнить JavaScript. Тип any можно обозначить несколькими способами.</p>
75
<p>Обратите внимание, есть неявный способ определить тип any с помощью ключевого слова Object:</p>
75
<p>Обратите внимание, есть неявный способ определить тип any с помощью ключевого слова Object:</p>
76
<p>Разработчики TypeScript решили присваивать тип any при использовании ключевого слова Object после анализа большого количества репозиториев, в которых использовался JSDoc. Многие программисты используют термин "object" неаккуратно, что не позволяет достоверно определить тип данных, который имеется в виду. Поэтому когда TypeScript видит в комментариях JSDoc соответствующее ключевое слово, он присваивает данным тип any.</p>
76
<p>Разработчики TypeScript решили присваивать тип any при использовании ключевого слова Object после анализа большого количества репозиториев, в которых использовался JSDoc. Многие программисты используют термин "object" неаккуратно, что не позволяет достоверно определить тип данных, который имеется в виду. Поэтому когда TypeScript видит в комментариях JSDoc соответствующее ключевое слово, он присваивает данным тип any.</p>
77
<p>Дальше рассказывается, как правильно определять тип данных object.</p>
77
<p>Дальше рассказывается, как правильно определять тип данных object.</p>
78
<h3>Сложные типы</h3>
78
<h3>Сложные типы</h3>
79
<p>Сложные типы данных порождают некоторые сложности. Как вы только что узнали, при использовании ключевых слов Object или object TypeScript определяет тип данных any. Чтобы определить тип объекта, нужно явно указать его. Если вы имеете дело с пустым объектным литералом, тип можно указать так:</p>
79
<p>Сложные типы данных порождают некоторые сложности. Как вы только что узнали, при использовании ключевых слов Object или object TypeScript определяет тип данных any. Чтобы определить тип объекта, нужно явно указать его. Если вы имеете дело с пустым объектным литералом, тип можно указать так:</p>
80
<p>Такой подход уместен, если вы не планируете добавлять свойства в объект. Если вы когда-то попробуете сделать это, то столкнётесь с проблемой, так как ранее определили тип - пустой объектный литерал.</p>
80
<p>Такой подход уместен, если вы не планируете добавлять свойства в объект. Если вы когда-то попробуете сделать это, то столкнётесь с проблемой, так как ранее определили тип - пустой объектный литерал.</p>
81
<p>Проблему можно решить, если при определении типа сообщить TypeScript о свойствах, которые могут появиться в объекте.</p>
81
<p>Проблему можно решить, если при определении типа сообщить TypeScript о свойствах, которые могут появиться в объекте.</p>
82
<h3>Открытые объекты</h3>
82
<h3>Открытые объекты</h3>
83
<p>Проблем со свойствами можно избежать, если указывать при определении типа открытые объекты.</p>
83
<p>Проблем со свойствами можно избежать, если указывать при определении типа открытые объекты.</p>
84
<p>Если планируете, что значениями свойств будут числа, это можно указать так:</p>
84
<p>Если планируете, что значениями свойств будут числа, это можно указать так:</p>
85
<p>Определение открытого объекта позволяет без проблем добавлять в него свойства.</p>
85
<p>Определение открытого объекта позволяет без проблем добавлять в него свойства.</p>
86
<p>Открытые объекты решают проблемы, которые есть у пустых объектных литералов. Но в данном случае у нас нет полезной информации о свойствах объектов. Всем новым свойствам присваивается тип any. Чтобы получить строгую информацию о типах свойств, необходимо создавать пользовательские свойства. Об этом пойдёт речь ниже.</p>
86
<p>Открытые объекты решают проблемы, которые есть у пустых объектных литералов. Но в данном случае у нас нет полезной информации о свойствах объектов. Всем новым свойствам присваивается тип any. Чтобы получить строгую информацию о типах свойств, необходимо создавать пользовательские свойства. Об этом пойдёт речь ниже.</p>
87
<blockquote><p>На Хекслете есть<a>раздел "Треки"</a>, в котором собраны курсы для глубокой проработки отдельных тем, например, асинхронности в JavaScript, ООП, тестирования. Регистрируйтесь и начинайте учиться, треки полезны как для начинающих, так и для опытных программистов!</p>
87
<blockquote><p>На Хекслете есть<a>раздел "Треки"</a>, в котором собраны курсы для глубокой проработки отдельных тем, например, асинхронности в JavaScript, ООП, тестирования. Регистрируйтесь и начинайте учиться, треки полезны как для начинающих, так и для опытных программистов!</p>
88
</blockquote><h3>Массивы</h3>
88
</blockquote><h3>Массивы</h3>
89
<p>Мы часто работаем с данными, упакованными в массивы. JSDoc позволяет легко определять типы массивов, с которыми мы работаем. Самый простой способ определить тип массива - определение типа данных, которые содержатся в этом массиве:</p>
89
<p>Мы часто работаем с данными, упакованными в массивы. JSDoc позволяет легко определять типы массивов, с которыми мы работаем. Самый простой способ определить тип массива - определение типа данных, которые содержатся в этом массиве:</p>
90
-
<p>Также можно определить массивы строк, чисел или объектов:</p>
90
+
<p>Также можно определить ма��сивы строк, чисел или объектов:</p>
91
<p>Можно определить массив объектов, это делается так:</p>
91
<p>Можно определить массив объектов, это делается так:</p>
92
<p>Когда мы рассмотрим создание пользовательских типов, вы сможете определять массивы пользовательских типов.</p>
92
<p>Когда мы рассмотрим создание пользовательских типов, вы сможете определять массивы пользовательских типов.</p>
93
<h3>Функции</h3>
93
<h3>Функции</h3>
94
<p>Проще всего определять функции с помощью тега @function.</p>
94
<p>Проще всего определять функции с помощью тега @function.</p>
95
<h3>Параметры функции</h3>
95
<h3>Параметры функции</h3>
96
<p>У функций могут быть параметры. Их можно определять с помощью тега @param. Далее указывается тип параметра в фигурных скобках, за которыми следует имя параметра.</p>
96
<p>У функций могут быть параметры. Их можно определять с помощью тега @param. Далее указывается тип параметра в фигурных скобках, за которыми следует имя параметра.</p>
97
<h3>Колбэки</h3>
97
<h3>Колбэки</h3>
98
<p>JSDoc позволяет определять<a>колбэки</a>и их аргументы. Подробности можно найти<a>в документации</a>.</p>
98
<p>JSDoc позволяет определять<a>колбэки</a>и их аргументы. Подробности можно найти<a>в документации</a>.</p>
99
<h3>Классы</h3>
99
<h3>Классы</h3>
100
<p>Поскольку работать с классами непросто, лучше обратиться<a>к документации</a>.</p>
100
<p>Поскольку работать с классами непросто, лучше обратиться<a>к документации</a>.</p>
101
<h2>Пользовательские типы</h2>
101
<h2>Пользовательские типы</h2>
102
<p>Иногда нужно использовать пользовательские типы, чтобы определить, что делает ваш код. В TypeScript для определения пользовательских типов применяются интерфейсы, так же как<a>в Java</a>или C#. В JavaScript нет интерфейсов, но вы можете получить нужный результат с помощью тега @typedef. Используйте его, чтобы определить основу пользовательского типа, а для определения его свойств используйте теги @prop или @property. Рассмотрим это на примере создания пользовательского типа Person.</p>
102
<p>Иногда нужно использовать пользовательские типы, чтобы определить, что делает ваш код. В TypeScript для определения пользовательских типов применяются интерфейсы, так же как<a>в Java</a>или C#. В JavaScript нет интерфейсов, но вы можете получить нужный результат с помощью тега @typedef. Используйте его, чтобы определить основу пользовательского типа, а для определения его свойств используйте теги @prop или @property. Рассмотрим это на примере создания пользовательского типа Person.</p>
103
<p>Мы определили тип Person, который можно использовать так:</p>
103
<p>Мы определили тип Person, который можно использовать так:</p>
104
<p>Мы определили, что аргументом функции выступает объект Person. Поэтому можно наверняка рассчитывать, что в этом объекте есть свойства name и age.</p>
104
<p>Мы определили, что аргументом функции выступает объект Person. Поэтому можно наверняка рассчитывать, что в этом объекте есть свойства name и age.</p>
105
<h2>Импорт типов</h2>
105
<h2>Импорт типов</h2>
106
<p>Если вы уже определили тип в одном модуле, можете импортировать его в другой модуль и использовать в нём. В импортах нужно указывать относительные пути. Синтаксис импорта типа выглядит так:</p>
106
<p>Если вы уже определили тип в одном модуле, можете импортировать его в другой модуль и использовать в нём. В импортах нужно указывать относительные пути. Синтаксис импорта типа выглядит так:</p>
107
<p>Вместо path надо указать путь к файлу, в котором определён тип. После закрывающей скобки ставится точка и указывается тип, который вы импортируете. После этого TypeScript сможет использовать импортированный тип в соответствующем модуле.</p>
107
<p>Вместо path надо указать путь к файлу, в котором определён тип. После закрывающей скобки ставится точка и указывается тип, который вы импортируете. После этого TypeScript сможет использовать импортированный тип в соответствующем модуле.</p>
108
<h2>Необязательные типы</h2>
108
<h2>Необязательные типы</h2>
109
<p>Иногда нужно определять необязательные параметры функций или свойства объектов. Опциональность можно отметить с помощью квадратных скобок. В примере ниже свойство age необязательное.</p>
109
<p>Иногда нужно определять необязательные параметры функций или свойства объектов. Опциональность можно отметить с помощью квадратных скобок. В примере ниже свойство age необязательное.</p>
110
<p>Таким же способом можно указывать необязательные параметры функций. В примере ниже в функцию можно не передавать аргумент age, ошибки не будет.</p>
110
<p>Таким же способом можно указывать необязательные параметры функций. В примере ниже в функцию можно не передавать аргумент age, ошибки не будет.</p>
111
<h2>Union Types (объединение типов)</h2>
111
<h2>Union Types (объединение типов)</h2>
112
<p>Иногда приходится работать со значениями разных типов. Это становится проблемой, если речь идёт о параметрах функций или методов. В этом случае можно использовать Union Types. Для этого надо перечислить возможные типы и разделить их пайпами:</p>
112
<p>Иногда приходится работать со значениями разных типов. Это становится проблемой, если речь идёт о параметрах функций или методов. В этом случае можно использовать Union Types. Для этого надо перечислить возможные типы и разделить их пайпами:</p>
113
<p>Такая запись позволяет передавать строки и числа в функцию announceAge.</p>
113
<p>Такая запись позволяет передавать строки и числа в функцию announceAge.</p>
114
<h2>Приведение типов</h2>
114
<h2>Приведение типов</h2>
115
<p>В вашем коде происходит приведение типов. Это возможно, когда в коде встречается значение с неоднозначным типом, а TypeScript может определить методы, которые вы вызываете с этим значением. Для приведения типов нужно определить тип и указать свойство в скобках. В примере ниже есть переменная sum, значение которой может быть разных типов. Попытка вызвать метод toFixed с этой переменной может привести к ошибке. Чтобы этого не произошло, нужно привести её тип к числу:</p>
115
<p>В вашем коде происходит приведение типов. Это возможно, когда в коде встречается значение с неоднозначным типом, а TypeScript может определить методы, которые вы вызываете с этим значением. Для приведения типов нужно определить тип и указать свойство в скобках. В примере ниже есть переменная sum, значение которой может быть разных типов. Попытка вызвать метод toFixed с этой переменной может привести к ошибке. Чтобы этого не произошло, нужно привести её тип к числу:</p>
116
<h2>Пропуск строки</h2>
116
<h2>Пропуск строки</h2>
117
<p>Если у вас трудности с корректным определением типов, можно отключить проверку типов для конкретной строки. Это делается так:</p>
117
<p>Если у вас трудности с корректным определением типов, можно отключить проверку типов для конкретной строки. Это делается так:</p>
118
<h2>Уменьшаем объём комментариев JSDoc</h2>
118
<h2>Уменьшаем объём комментариев JSDoc</h2>
119
<p>Сторонники использования TypeScript приводят аргумент против комментариев JSDoc - они очень объёмные по сравнению с TypeScript. Если вы не используете JSDoc для создания документации, можно сократить комментарии, удалив из них лишние астериксы в начале каждой строки.</p>
119
<p>Сторонники использования TypeScript приводят аргумент против комментариев JSDoc - они очень объёмные по сравнению с TypeScript. Если вы не используете JSDoc для создания документации, можно сократить комментарии, удалив из них лишние астериксы в начале каждой строки.</p>
120
<p>На иллюстрации показан способ определения сложных типов с использованием более лаконичного варианта комментариев JSDoc.</p>
120
<p>На иллюстрации показан способ определения сложных типов с использованием более лаконичного варианта комментариев JSDoc.</p>
121
<p>На следующей иллюстрации показано определение этих типов на TypeScript.</p>
121
<p>На следующей иллюстрации показано определение этих типов на TypeScript.</p>
122
<p>Как видно, разница в объёме кода невелика. Сокращённая версия JSDoc теряет подсветку синтаксиса, но всё равно остаётся читабельной. Поэтому выбор между использованием TypeScript и JSDoc - вопрос предпочтений. Хотите писать на чистом JavaScript и иметь типобезопасность? Пользуйтесь JSDoc. Хотите писать на другом языке, который обеспечивает типобезопасность и компилируется в JavaScript? Тогда используйте TypeScript, Reason, Elm и так далее.</p>
122
<p>Как видно, разница в объёме кода невелика. Сокращённая версия JSDoc теряет подсветку синтаксиса, но всё равно остаётся читабельной. Поэтому выбор между использованием TypeScript и JSDoc - вопрос предпочтений. Хотите писать на чистом JavaScript и иметь типобезопасность? Пользуйтесь JSDoc. Хотите писать на другом языке, который обеспечивает типобезопасность и компилируется в JavaScript? Тогда используйте TypeScript, Reason, Elm и так далее.</p>
123
<h2>Как настроить проект</h2>
123
<h2>Как настроить проект</h2>
124
<p>Для вашего удобства я создал на GitHub проект check-js, в котором есть линтинг типов одновременно в режиме реального времени и при сборке. Откровенно говоря, это очень простой проект. В нём используются ESLint, Prettier, юнит-тесты с помощью Jest и проверка типов. Вы можете самостоятельно настроить ESLint и Prettier, а также использовать другой инструмент для юнит-тестирования на своё усмотрение. Проект доступен<a>по ссылке</a>.</p>
124
<p>Для вашего удобства я создал на GitHub проект check-js, в котором есть линтинг типов одновременно в режиме реального времени и при сборке. Откровенно говоря, это очень простой проект. В нём используются ESLint, Prettier, юнит-тесты с помощью Jest и проверка типов. Вы можете самостоятельно настроить ESLint и Prettier, а также использовать другой инструмент для юнит-тестирования на своё усмотрение. Проект доступен<a>по ссылке</a>.</p>
125
<h3>tsconfig.json</h3>
125
<h3>tsconfig.json</h3>
126
<p>Чтобы Visual Studio Code лучше понимал структуру вашего проекта и типы, которые в нём используются, можно создать в корне проекта файл tsconfig.json и указать в нём соответствующие данные. Вот пример файла tsconfig.json.</p>
126
<p>Чтобы Visual Studio Code лучше понимал структуру вашего проекта и типы, которые в нём используются, можно создать в корне проекта файл tsconfig.json и указать в нём соответствующие данные. Вот пример файла tsconfig.json.</p>
127
<p>Обратите внимание, как указывается путь: src/index.js. Также обратите внимание на свойство exclude, в котором указаны исключения. Однозначно нужно указывать здесь node_modules. Также TypeScript должен игнорировать директорию types, в которой находятся автоматически сгенерированные файлы d.ts. Директория с тестами также указана в исключениях, в данном примере она называется __tests__. Если вы используете конфигурацию, указанную в примере выше, проверку типов в терминале можно запускать с помощью следующего скрипта:</p>
127
<p>Обратите внимание, как указывается путь: src/index.js. Также обратите внимание на свойство exclude, в котором указаны исключения. Однозначно нужно указывать здесь node_modules. Также TypeScript должен игнорировать директорию types, в которой находятся автоматически сгенерированные файлы d.ts. Директория с тестами также указана в исключениях, в данном примере она называется __tests__. Если вы используете конфигурацию, указанную в примере выше, проверку типов в терминале можно запускать с помощью следующего скрипта:</p>
128
<p>Кроме проверки типов, он также создаёт файлы с определениями типов d.ts. Вы можете обновить файл package.json, чтобы сделать эти типы доступными вашим пользователям:</p>
128
<p>Кроме проверки типов, он также создаёт файлы с определениями типов d.ts. Вы можете обновить файл package.json, чтобы сделать эти типы доступными вашим пользователям:</p>
129
<p>Конечно, сначала нужно установить TypeScript не ниже версии 3.7.3. Для этого воспользуйтесь командой:</p>
129
<p>Конечно, сначала нужно установить TypeScript не ниже версии 3.7.3. Для этого воспользуйтесь командой:</p>
130
<p>После этого можно запустить проверку:</p>
130
<p>После этого можно запустить проверку:</p>
131
<h2>Пакетный импорт</h2>
131
<h2>Пакетный импорт</h2>
132
<p>Если вы используете TypeScript версии 3.7.3 и выше, можно пользоваться пакетным импортом типов. Мне нравится такой подход: указываем все типы в файле types.js в корневой директории, а когда необходимо импортировать типы в другой модуль, делаем это так:</p>
132
<p>Если вы используете TypeScript версии 3.7.3 и выше, можно пользоваться пакетным импортом типов. Мне нравится такой подход: указываем все типы в файле types.js в корневой директории, а когда необходимо импортировать типы в другой модуль, делаем это так:</p>
133
<p>Используйте подходящее пространство имён для своего проекта. Из этого пространства имён можно получить доступ к типам:</p>
133
<p>Используйте подходящее пространство имён для своего проекта. Из этого пространства имён можно получить доступ к типам:</p>
134
<h2>Примеры</h2>
134
<h2>Примеры</h2>
135
<p>Если хотите посмотреть, как работает проверка типов в реальности, загляните в проекты из<a>этого репозитория</a>. В них реализован линтинг типов в реальном времени, а также возможность запустить проверку в терминале с помощью команды npm test.</p>
135
<p>Если хотите посмотреть, как работает проверка типов в реальности, загляните в проекты из<a>этого репозитория</a>. В них реализован линтинг типов в реальном времени, а также возможность запустить проверку в терминале с помощью команды npm test.</p>
136
<p>Адаптированный перевод статьи<a>JavaScript Type Linting</a>by Robert Biggs. Мнение администрации Хекслета может не совпадать с мнением автора оригинальной публикации.</p>
136
<p>Адаптированный перевод статьи<a>JavaScript Type Linting</a>by Robert Biggs. Мнение администрации Хекслета может не совпадать с мнением автора оригинальной публикации.</p>