Мигрируем с JavaScript на TypeScript быстро и безболезненно

Мигрируем с JavaScript на TypeScript быстро и безболезненно

Хотите воспользоваться преимуществами строго типизированного языка, но боитесь сложной конфигурации? Мы покажем, как легко и быстро ввести TypeScript в ваш проект.

JavaScript – чрезвычайно гибкий и простой в изучении и работе язык. Крупное активное сообщество и масса преимуществ. Однако и подводных камней не меньше. Большинство из них связаны с избыточной свободой программиста. Сегодня мы взглянем на TypeScript – более строгую версию классического JS.

Миграция без изменения сборки

Проще всего отказаться от JavaScript, когда вы начинаете проект с чистого листа: можно не задумываться о совместимости изменений. Но что, если нужно поддерживать и развивать старые программы? Изменение языка разработки кажется плохой идеей, ведь придётся переписать десятки файлов. Долго, скучно, а главное – легко сломать налаженный процесс сборки проекта.

Но TypeScript является надмножеством JavaScript и полностью с ним совместим. Если скормить TS-компилятору JS-код, он не будет возражать. Миграцию на TypeScript можно проводить постепенно, файл за файлом. Писать новые скрипты на TypeScript, а существующие –переписывать в удобном темпе.

Попробуем добавить TypeScript в имеющийся проект, не меняя конфигурации webpack, gulp или другого сборщика, которым вы пользуетесь.

Шаг 1. Устанавливаем и настраиваем TypeScript

Прежде всего нужно установить TypeScript в приложение (или глобально):

 npm install --save-dev typescript 

Примечание: в зависимости от проекта вам могут потребоваться также пакеты типов (@types) для различных библиотек. Например, для react-redux нужно установить следующие модули:

 npm install --save-dev @types/node
npm install --save-dev @types/react
npm install --save-dev @types/react-dom
npm install --save-dev @types/react-redux
npm install --save-dev @types/react-router-dom 

Теперь добавим в корень проекта файл tsconfig.json. В нём будут содержаться настройки компилятора, необходимые для конвертации. Возьмите для начала предлагаемую ниже конфигурацию. Она обеспечивает полную совместимость JS и TS синтаксисов.

tsconfig.json
 { "compilerOptions": { "module": "commonjs", "sourceMap": true, "jsx": "react" }, "exclude": [ "node_modules" ]
} 

Чтобы настроить конфигурационный файл под нужды вашего проекта, обратитесь к документации TypeScript.

Теперь в секцию scripts файла package.json добавим команду для компиляции:

package.json
 "tsc:w": "tsc -w" 

При запуске в терминале все файлы с расширением .ts или .tsx будут транслированы в js-файлы. Утилита разместит их по тому же пути, а значит, сборщик сможет работать как раньше, игнорируя ts-исходники.

Примечание: если в проекте нет ни одного .ts-файла, в консоли появится ошибка. Не пугайтесь, команда работает в режиме наблюдения. Как только вы создадите первый typescript-файл, компиляция заработает правильно.

Результат компиляции TypeScript-файла
 file.ts
├── file.js
└── file.js.map 

А теперь пусть начнётся магия 💫. Берём любой JS-файл, и меняем расширение на .ts. Компилятор обрабатывает его без возражений.

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

Добавим строгости

Большой прыжок вперёд с технической точки зрения, но в самой разработке ничего не поменялось: ни нового кода, ни преимуществ TypeScript.

Создадим простое приложение, определяющее, может ли пользователь взять ипотечный кредит.

Напишем функцию getSavings, которая будет собирать информацию о доходах и сбережениях клиента:

 function getSavings() {
//returns savings
} 

На основании этих данных функция concedeMortgage будет принимать решение о выдаче кредита:

 function concedeMortgage(homeValue) { const savings = getSavings(); return savings / homeValue > 0.2;
} 

Чтобы приложение работало нормально, необходимо добавить проверку входных данных. Существует ли значение homeValue, является ли оно числом? Кроме того, нужно убедиться, что функция getSavings() возвращает корректное значение сбережений. Итак, код немного разрастается:

 function concedeMortgage(homeValue) { if(!homeValue || !parseFloat(homeValue)) return false; const savings = getSavings(); if(!savings || !parseFloat(savings)) return false; return savings / homeValue > 0.2;
} 

Это выглядит некрасиво, пора воспользоваться преимуществами TypeScript.

noImplicitAny

Добавьте в файл tsconfig.json в секцию compilerOptions новую опцию:

tsconfig.json
 "noImplicitAny": true 

Можно не проверять, являются ли входное значение и результат работы getSavings числами. Мы просто укажем нужный тип. Проверки станут короче:

 function concedeMortgage(homeValue: number): boolean { if(!homeValue) return false; const savings = getSavings(); if(!savings) return false; return savings / homeValue > 0.2;
} 

Теперь можно отловить ошибку типа на стадии компиляции! TypeScript не позволит вызвать функцию concedeMortgage, например, со строковым значением:

 concedeMortgage("foo");
// ERROR! Argument of type 'foo' is not assignable to parameter type 'number' 

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

 concedeMortgage(null) 

Не переживайте, сейчас мы это поправим.

strictNullChecks

Активируйте опцию компилятора:

tsconfig.json
 "strictNullChecks": true 

Теперь вызов функции с null также приводит к ошибке. Можно убрать все проверки и вернуть concedeMortgage к первозданному чистому виду:

 function concedeMortgage(homeValue: number): boolean { const savings = getSavings(); return savings / homeValue > 0.2;
} 

***

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

А вы уже используете TypeScript в своих проектах?

proglib.io

Добавить комментарий

Ваш e-mail не будет опубликован.

4 × пять =