TypeScript (TS) позволяет использовать аннотации типов в коде JavaScript. TS даже может проверять код при сборке, благодаря чему вы увидите ошибки до того, как они попадут в продакшен. Вы избавитесь от undefined is not a function
навсегда.
- Синтаксис TypeScript
- Документируем JavaScript
- Установка TypeScript
- Базовые аннотации
- Документирование параметров
- Утверждения типов (Type Assertions)
- Импорт определений типов
- Определение типов в файлах JavaScript
- Определение типов в React
- Расширенные возможности
- Резюме
TypeScript по умолчанию требует некоторых изменений при настройке окружения. Вам придётся переименовать файлы JavaScript в .ts, .tsx, а также использовать компиляторы tsc или Babel.
Синтаксис TypeScript
Часто людям не нравится работать с TypeScript из-за необходимости использовать новый для них синтаксис. Если вам знакома эта ситуация, статья как раз для вас.
function repeat(text: string, count: number) {
return Array(count + 1).join(text)
}
Синтаксис TypeScript позволяет использовать аннотации типов инлайн. Но сначала поговорим об альтернативах.
Документируем JavaScript
Синтаксис JSDoc
TypeScript можно документировать с помощью JSDoc. Это стандартный синтаксис для документирования JavaScript. JSDoc используется для создания документации, но TypeScript понимает аннотации типов, созданные с помощью этого инструмента.
/**
* Repeats some text a given number of times.
*
* @param {string} text - The text to repeat
* @param {number} count - Number of times
*/
function repeat(text, count) {
return Array(count + 1).join(text)
}
Это значит, что у вас есть возможности использовать преимущество TypeScript, в частности, проверку типов, без необходимости конвертировать весь код.
Почему JSDoc
Применение JSDoc — полезная практика, даже если вы не используете TypeScript. Фактически это стандарт документирования JavaScript, и его поддерживают разные инструменты и редакторы.
Если вы уже применяете JSDoc, вам будет удобно использовать проверку типов в коде, аналогичную той, которая применяется в TypeScript. Для этого нужно уделить время настройке TypeScript.
Установка TypeScript
Как установить TypeScript
Чтобы установить в проект TypeScript, используйте такую команду:
npm install typescript
# или
yarn add typescript
Как включить проверку типов JSDoc
Теперь нужно настроить TypeScript, чтобы он проверял код в файлах JavaScript. По умолчанию он проверяет только файлы с расширением .ts
. Настройки TypeScript надо указывать в файле tsconfig.json
. Обратите внимание на опцию noEmit
. Мы используем её, так как планируем применять TypeScript только для проверки типов.
{
"compilerOptions": {
"allowJs": true,
"noEmit": true
}
}
Настраиваем TypeScript
В начале файлов .js
, в которых вам нужна проверка типов, добавьте комментарий:
// @ts-check
Запустите проверку типов. Это можно сделать с помощью команды:
./node_modules/.bin/tsc
# или
yarn run tsc
Рекомендуется использовать проверку типов также в инструментах непрерывной интеграции (CI).
Дальше поговорим о документировании кода с помощью JSDoc.
Базовые аннотации
Аннотации параметров функций
Для аннотации параметров функций используйте @param
. Его нужно указать в комментариях JSDoc, которые начинаются с двух идущих подряд астериксов.
/**
* @param {string} текст
* @param {number} количество
*/
function repeat(text, count) {
return Array(count + 1).join(text)
}
Документирование кода
JSDoc — инструмент для документирования. Кроме добавления аннотаций типов, вы можете документировать функции.
/**
* Повторяет текст заданное количество раз
*
* @param {string} text - Текст
* @param {number} count - Количество повторений
*/
function repeat(text, count) {
return Array(count + 1).join(text)
}
Потренируемся в документировании.
Документирование параметров
Опциональные типы
Чтобы показать опциональность типа, добавьте после него знак равенства. В примере ниже number=
— то же самое, что и number | null | undefined
. Такой синтаксис можно использовать только в типах JSDoc.
/**
* @param {string} text
* @param {number=} count
*/
function repeat(text, count = 1) {
// ...
}
Документируем опции
Вы можете документировать свойства параметров, например, options.count
или options.separator
. Эту возможность можно использовать для документирования props
в функциональных компонентах React.
/**
* @param {string} text - Text to repeat
* @param {Object} options
* @param {number} options.count
* @param {string} options.separator
*/
function repeat(text, options) {
console.log(options.count)
console.log(options.separator)
// ...
}
repeat('hello', { count: 2, separator: '-' })
Утверждения типов (Type Assertions)
Переменные
Используйте @type
, когда пишете инлайн определение для аргументов функций. Это обычно избыточно для констант, так как TypeScript чётко работает с типами. Подход полезен при работе с изменяемыми данными, например, с переменными.
/**
* Time out in seconds.
* @type number
*/
let timeout = 3000
Параметры функций
@type
можно использовать для определения типов аргументов функций инлайн. Это особенно удобно при работе с анонимными функциями.
list.reduce((
/** @type number */ acc,
/** @type number */ item
) => {
return acc + item
}, 0)
Далее поговорим о выносе определений типов в отдельные файлы.
Импорт определений типов
Импортируем типы
Сложные и переиспользуемые типы лучше определять во внешних файлах. Они имеют расширение .d.ts
. Обратите внимание, это должны быть именно файлы TypeScript. Импортировать определения из файлов JavaScript невозможно.
Типы можно импортировать с помощью представленного ниже синтаксиса. Определения должны определяться во внешних файлах с расширением .d.ts
, как сказано выше.
/** @typedef { import('./myTypes').User } User */
/**
* @param {User} author
*/
function cite(author) {
// ...
}
Определяем типы во внешних файлах
Ниже представлен синтаксис определения типов во внешних файлах TypeScript. Ещё раз обратите внимание, импортировать определения типов из файлов JavaScript невозможно.
/* myTypes.d.ts */
export interface User {
name: string
email: string
}
Теперь разберёмся, можно ли определять типы в JavaScript-файлах.
Определение типов в файлах JavaScript
Типы объектов
Для определения типов объектов используйте @typedef
. Предпочтительно делать это во внешних файлах с расширением .d.ts
. Но вы можете использовать представленный ниже синтаксис и в файлах JavaScript.
/**
* @typedef {Object} Props
* @property {string} title - The title of the page
* @property {number} updatedAt - Last updated time
*/
/**
* A component.
*
* @param {Props} props
*/
const ArticleLink = props => {
console.log(props.title)
console.log(props.updatedAt)
// ...
}
Объединение типов
Используйте объединение типов (|
) для определения двух или более возможных вариантов. Для простоты используйте @typedef
.
/** @typedef {number | string} NumberOrString */
Как насчёт React?
Определение типов в React
Функциональные компоненты
Функциональные компоненты представляют собой функции. Поэтому вы можете документировать их способами, о которых говорилось выше в разделе о документировании функций. В следующем примере показано документирование с помощью типов объектов.
/**
* This is a React function component.
*
* @param {Object} props
* @param {string} props.title
* @param {string} props.url
* @param {string} props.image
*/
const ArticleLink = props => {
// ...
}
Подробности о функциональных компонентах можно узнать в курсе по React, который входит в профессию «Фронтенд JavaScript».
Компоненты на классах
Используйте @extends
для определения типов props
и state
. Также для решения этой задачи можно использовать @typedef
инлайн или с импортом.
/**
* This is a React class component.
*
* @extends {React.Component<Props, State>}
*/
class MyComponent extends React.Component {
// ...
}
Расширенные возможности
Синтаксис JSDoc не такой выразительный, как TypeScript, но эти инструменты всё-таки похожи. Ниже перечислены некоторые дополнительные возможности TS, доступные в JSDoc.
- Темплейты —
@templates
. - Возврат значений —
@returns
. - Условия типов —
@returns
. - Функциональные типы —
@callback
. - Перечисления —
@enum
.
Ещё больше возможностей найдёте в официальной документации.
Резюме
Ниже представлены перечисленные в статье способы работы с аннотациями типов.
Проверка типов JavaScript
// @ts-check
Документирование функций
/**
* Multiply a number by itself.
* @param {number} n - What to square
*/
function square(n) {
// ...
Импорт определений типов (позволяет определять типы во внешних файлах)
/** @typedef { import('./myTypes').User } User */
Опциональные типы
/** @param {User=} user */
Анонимные функции
numbers.map((/** @type number */ n) => {
return n * 2
})
Документирование свойств параметров объектов
/**
* @param {Object} options
* @param {number} options.count
* @param {string} options.sep
*/
function repeat(options) {
// ... options.count, options.sep
Адаптированный перевод статьи Type annotations in JavaScript files by Rico Sta. Cruz. Мнение администрации Хекслета может не совпадать с мнением автора оригинальной публикации.