8 сентября 2020 г., 35 минут на прочтение
Несколько дней назад Дэвид Хайнемайер Ханссон объявил, что Turbo 8 отказывается от TypeScript. Что касается меня, то мне это подходит, потому что я даже не знаю, что такое Turbo 8. Однако за последние несколько лет некоторые программисты, занимающиеся разработкой клиентской части веб-приложения, пытались внушить мне идею, что «TypeScript бесполезен, просто используйте тесты». Я думаю, что люди с таким мнением либо не заботятся о качестве кода, либо просто не знают, что такое TypeScript. В этой статье я объясню, почему вам следует использовать TypeScript.
Контроль качества кода — это сложный процесс, обеспечивающий создание легкого в сопровождении кода. Вы не можете просто охватить код тестами на 100 % или просмотреть каждый запрос на включение и быть уверенным в том, что ваш код легкий в сопровождении, и что кто-то кроме вас сможет разобраться в этом бардаке.
Вы вообще не можете гарантировать, что ваш код не содержит ошибок и идеально легок в сопровождении. Вы можете только усилить защитные структуры в своем репозитории, чтобы затруднить распространение плохого кода с ошибками. Чем больше у вас барьеров для плохого кода, тем лучше качество вашего кода.
Это означает, что вы должны использовать все методы для защиты кода в вашем репозитории: модульное/e2e/комплексное тестирование, проверку кода, инструменты анализа кода, а также вести четкую документацию и т. д.
TypeScript — мощный инструмент анализа кода; он может обнаружить множество дефектов в коде. Компилятор TypeScript заставляет программистов обеспечивать правильность кода на уровне типов. Ценность статической проверки типов недооценивается Дэвидом и многими другими.
Давайте посмотрим, какие преимущества дает TypeScript для качества кода.
Контракты
Статические типы позволяют определять контракты в коде.
type Participant = {
id: string;
name: string;
};
function sayHi(participant: Participant) {
//…
console.log(`Hi ${participant.name}`);
}
Функция sayHi требует объекта с точными свойствами и точными типами, и совершенно неважно, что сделает пользователь этой функции, чтобы выполнить требования. Компилятор гарантирует, что тип будет правильным.
Пользователь может предоставить объект, который не соответствует требованиям, и привести тип к any, но это не проблема для функции sayHi. Это передача ответственности, важная концепция, которую разработчики должны понимать, чтобы правильно использовать TypeScript и извлекать из этого выгоду.
Программисты должны проверять любые ненадежные данные, такие как ввод информации пользователем и другие данные ввода-вывода, а также результаты взаимодействия с JavaScript. После проверки и установки типов они могут передать данные в код TypeScript и быть уверенными в том, что контракты будут действительны, поскольку компилятор TypeScript проверил код. Если программист выполняет приведение типа, он должен проверить правильность кода во время выполнения.
Если вы можете привести непересекающиеся типы в своем проекте к любым типам, кроме unknown без проверки во время выполнения, вероятно, в вашем проекте имеются проблемы с качеством кода.
Контракты позволяют избежать написания проверки для каждой функции, чтобы гарантировать правильность данных. Это сильно сказывается как на производительности, так и на чистоте кода, код становится глупым и простым.
Простота и скорость разработки и расходы на разработку
Иногда я пишу код на чистом JavaScript, в основном в консоли браузера для быстрых вычислений или анализа данных на веб-странице. Несколько месяцев назад я написал скрипт для Node.js для перевода файлов локали с использованием ChatGPT. Эти файлы содержали длинные тексты, а у ChatGPT были ограничения, поэтому требовалось некоторое время, чтобы нарезать тексты, перевести их, найти ошибки в результатах ChatGPT, выполнить повторный перевод по мере необходимости, а затем снова соединить фрагменты. Этот процесс занял около 3–5 минут в зависимости от размера файла локали.
В ходе выполнения этого процесса я потратил некоторое время впустую из-за тривиальных ошибок типа, например, из-за того, что забыл использовать await, что привело к тому, что переменная содержала Promise, записал «[object Promise]» в файл вместо переведенного текста, или задал не тот объект в качестве аргумента функции.
TypeScript устраняет подобные ошибки.
Инвестиции в будущее
TypeScript дает возможность проанализировать ваш код с помощью других инструментов, поскольку добавляет контекст.
С помощью IDE вы можете переименовать свойство в интерфейсе, и все сущностные объекты, реализующие интерфейс, автоматически обновят имя свойства в соответствующих местах.
Инструменты искусственного интеллекта, такие как ChatGPT и Copilot, извлекают выгоду из дополнительной метаинформации, предоставляемой TypeScript, что потенциально улучшает анализ и генерацию кода. Инструменты анализа позволяют лучше выявлять потенциально опасный код.
Статическая проверка типов и тесты прекрасно дополняют друг друга. Код клиентской части приложения очень асинхронен, что затрудняет охват всех возможных тестовых вариантов и рассмотрение всех потенциальных состояний кода. TypeScript заставляет программистов обрабатывать все возможные варианты, которые могут возникнуть в состоянии, повышая надежность кода.
Сложность типов
Дэвид говорит
TypeScript мне только мешает. Не только потому, что он требует явного шага компиляции, но и потому, что он загрязняет код упражнениями с типами, что доставляет мне мало радости в процессе разработки, а зачастую и приносит немалое огорчение. Вещи, которые должны быть легкими, становятся трудными, а трудные становятся any. Нет, спасибо!
Я цитирую это, потому что слышал такую точку зрения много раз.
Это правда, что иногда вам приходится писать нетривиальные типы, чтобы убедить компилятор в правильности ваших данных.
Это нормально. Создание качественного кода, легко поддающегося изменениям и дополнениям, часто требует тяжелой работы.
Заключение
TypeScript — это всего лишь инструмент, он не улучшит качество кода автоматически, если вы просто включите его. В вашем проекте должны быть установлены правила правильного использования инструмента, а также разработчик архитектуры, который будет обеспечивать соблюдение этих правил. Чем строже правила, тем лучше.
Когда вы отключаете статические типы в своем проекте, вы теряете многие возможности по контролю качества кода.
JSDoc и .d.ts файлы объявлений типов не могут заменить статическую проверку типов кода. Это просто способы объявления внешнего API сущностных объектов, но они не позволяют анализировать код внутри сущностных объектов (функций, классов и других блоков кода).