Вот почему тебе нужен этот загадочный TypeScript
TypeScript используют во многих крупных проектах: на нём написаны VS Code и Angular. Он был в трендах на GitHub и активно обновляется Microsoft.
TypeScript сокращает количество unit-тестов
Первая причина перейти на TypeScript – трата огромного количества времени на тестирование своего кода. Вы уже писали тесты? Тогда рассчитывайте на 10-20% уменьшение объёмов требуемого кода. А если никогда не писали, то получите всё те же 20% без каких-либо затрат!
Эта простая функция говорит о второй проблеме: да, в JS есть типы, нравится вам это или нет. Но в юнит-тестах вы должны удостовериться, что функция отбрасывает неопределённые и аргументы без значений, строки, etc. Ещё один тест – удостовериться, что функция всегда возвращает правильное число, к примеру, ненулевое значение.
В TypeScript все эти тесты могут присутствовать в самом языке. Вы вольны указать не только явно числовой тип a
, b
и результату, но ещё и их значения как nullable.
Сначала был tsc, и tsc был с TypeScript
Давайте настроим небольшой проект. Самый простой способ использовать TypeScript – tsc
. Это означает «TypeScript compiler» – простейший инструмент, включённый в сам TypeScript. Он позволяет компилировать любые .ts
файлы в .js
.
npm install –global typescript
Создайте первый ts-файл:
Просто скомпилируйте этот файл с помощью tsc
, что создаст исполняемый файл test.js:
tsc test.ts node test.js
Получили 123? Отлично! Вы уже используете TypeScript. Что значит «Это всё тот же JavaScript»? Вы уверены? Давайте попробуем другой код:
В VS Code вы получите предупреждение о неверном синтаксисе. Не используете VS Code? Скомпилируйте файл с помощью tsc
, и увидите:
Видите? Это чистый JavaScript, между тем вы уже начали защищать ваш код.
Немного о конфиге
TypeScript предоставляет много конфигов для кастомизации вашего рабочего процесса. Для инструкций из этой статьи рекомендуется общий и гибкий конфиг:
Для тех, кому не лень, есть дополнительные строчки конфига, которые упрощают процесс работы с tsc
и заносятся в tsconfig.json
:
Мы добавили две вещи: свойство include
, которое указывает на местоположение исходников и outDir
– местоположение выходных файлов. Если теперь вы положите test.ts
в папку src/
, рядом с другими ts-файлами, то запустив tsc
без аргументов, получите такую же структуру, как вывод в папке dist
:
Далее, чтобы не вводить tsc
при каждом изменении, вы можете использовать tsc - watch
, которая будет обновляться каждый раз при изменении файлов.
TypeScript сказал типам «Да»
Смотрите, как ввести типизацию в свою ежедневную работу, не сломав при этом голову. Начнём с простого представления:
Легко, не так ли? Просто добавьте :
к переменной, чтобы объявить её тип. Ещё вы можете указать тип функции и возвращаемого значения:
Ещё одна крутая фича TypeScript – проверка notNullable
. Включите её в своём конфиге:
А затем:
Легко, не так ли?
Когда указывать типы
Вот в чём вопрос: когда нужно указывать типы, а когда они не нужны?
Большое количество людей настаивают на настройке TypeScript в строгой форме. Люди аргументируют типизацию всего и вся, исходя из сравнения TypeScript с Java и C. Но это дело личных предпочтений.
Помните, что из-за динамичности и гибкости JS, типизация всего может обернуться в объявления из 3-4 строк.
Проверяйте читаемость кода. Типы могут испортить его восприятие. Возможно, большинство недоразумений происходят от бэкграунда JS-разработчика, который видит в типах инструмент безопасности кода, в то время как типы в C связаны с управлением памятью. Другими словами, C использует типы для эффективного выделения памяти в зависимости от количества информации, хранимой в переменной. JavaScript не может использовать эту информацию в такой же степени.
Так всегда ли полезны типы, когда выбор остаётся за разработчиком?
Сложно найти однозначный ответ, поэтому придерживайтесь простого правила, которое составляет 80/20 эффективности TypeScript:
Указывайте типы хотя бы для параметров функции и возвращаемого значения.
Когда вы пишете код, вы создаёте блоки, которые являются функциями. Указание типов хотя бы для входа/выхода каждой функции в долгосрочной перспективе означает, что при 20% работы вы получаете 80% защиты типов. Каждый раз, когда кто-то обновляет функцию, вы ждёте, что она будет делать то же самое. Если возврат параметров поменяется, вы получите ошибку.
Причина, по которой типизация суммы необязательна, очевидна: при написании функции вы видите её целиком, и поймать ошибку становится намного легче, чем искать её в совсем другом файле! А если вы столкнулись с неправильной работой самой функции, попробуйте написать unit-тест, чтобы сделать функцию стабильнее, вместо того, чтобы вводить дополнительную типизацию.
Используете React? Забудьте Proptypes: используйте TypeScript для явной типизации пропсов и состояний.
TypeScript разделяет проекты
Насладитесь установкой кастомного типа для библиотеки. Допустим, проект использует React, и мы хотим его типизировать.
Кажется, забыли установить React, на что TypeScript указывает в ошибке. Круто, правда?
Установите React и его типы. Введите в терминал:
npm install react @types/react
Запустите команду tsc
, и TypeScript предложит вам обзор базового использования React.
Как это работает?
Когда вы выполняете npm install
, npm создаёт папку @types в node_modules. В этой папке вы увидите файл .d.ts, который называется файлом «определения» в TypeScript. Он выглядит сложным, но TypeScript генерирует его за вас.
Продвинутые типы
Здесь мы не будем раскрывать все возможности TypeScript, рассмотрим только трюки с продвинутыми типами, чтобы прокачать TS :)
Начнём с простых интерфейсов. Они являются простым способом типизации JSON. Хорошая практика – начинать название интерфейса с заглавной буквы «I»:
Избегайте тысяч интерфейсов в файле interface.ts. Будьте внимательны к своей модели данных и храните интерфейсы ближе к их генераторам (пример: api./папки).
Ещё один полезный трюк – оператор объединения. Так как иногда функция может возвращать множественные значения, используйте |
, чтобы раскрыть их:
Если сложность возрастает, TypeScript поддерживает перегрузку.
writeFile(id: string, data: string, callback: TCallback<void>); writeFile(id: string, data: string, options: IWriteFileOptions | string, callback: TCallback<void>);
При определении массива вы можете явно указать, что в него можно положить:
Приведение типов
Приведение типов – концепция, которая заимствована из типизированных языков. Иногда вы будете получать переменные из внешних источников без указания типов этих переменных. Далее укажите TypeScript тип этих переменных.
Типы кастомных библиотек
Если хотите добавить собственную документацию к библиотеке без типов, создайте кастомный тип. Добавьте папку @types в корень вашего проекта и подпапку с названием библиотеки для типизации. Для примера возьмём React.
Создайте файл определения:
А затем просто добавьте папку @types/**/* в include вашего tsconfig.
Заключение
Сам по себе TypeScript является относительно новым языком, и вам понадобится немного времени, чтобы постичь искусство типизации.
Начните с официальной документации.