Постепенно вводим TypeScript в ваш проект на React
В последнее время в области front-end особую популярность приобретает комбинация React+TypeScript. Соответственно, возрастает актуальность грамотной миграции с JavaScript на TypeScript, желательно в сжатые сроки. Сегодня мы хотели бы обсудить с вами именно эту тему.

Как безопасно собирать и вводить компоненты React TypeScript в ваш проект React JS.
Почему может потребоваться миграция с JS на TS? Причин на то может быть огромное множество, но суть не в этом. (Гипотетический) факт заключается в следующем: вам необходимо приступить к использованию TypeScript, и нужен легкий путь внедрения его в ваш проект. Мало того, все это нужно как-то сделать, не нарушив структуры всего имеющегося кода, и убедив команду в необходимости такого перехода.
Здесь будет продемонстрирован постепенный рефакторинг: как встраивать компоненты React в другую базу кода, а затем при помощи Bit безопасно вводить их в уже работающее приложение React на JavaScript.
Безопасное встраивание компонентов TS в проект на JS при помощи Bit

Существует множество способов перейти с React JS на React TS. Суть данной статьи – показать, как это делается поступательно. Аналогичный метод применим и в других случаях.
Базовая идея заключается в том, чтобы выжать максимум из компонентов React + при помощи Bit изолировать их друг от друга в собственной среде разработки Bit. В совокупности это позволяет собирать компоненты TS и безопасно вводить их в полнофункциональное приложение React JS.
Bit – это опенсорсный инструмент для извлечения компонентов из репозиториев Git. Bit позволяет собирать компоненты TS вне проекта, написанного на JS, выделяя под каждый автономную изолированную среду разработки, которая может работать и в других проектах, независимо от их конфигураций. Затем вы можете просто версионировать и «бит-импортировать» эти компоненты в ваш проект на JS, и они будут работать.
Наряду с Bit существует Bit.dev – удаленный хаб, в котором можно хранить эти компоненты, чтобы затем использовать повторно. Мы будем держать в Bit.dev компоненты TS, а оттуда станем вводить их в наш проект на React JS.
Пример: поиск разделяемых компонентов React в bit.dev
Пример использования
Для целей этой статьи разберем пример, который в мире фронтенда сравним с классическим “hello world”: речь пойдет о приложении для планирования дел.
Не волнуйтесь, я не собираюсь рассказывать вам, как написать такое приложение для React. Предполагаю, вы уже умеете это делать и, будем честны, тема уже далеко не новая, так что увольте.
Но я воспользуюсь вот этим приложением в качестве примера – можете с полным правом делать его форк или, как минимум, откройте ссылку и посмотрите весь его код.

Данная база кода состоит из следующих компонентов:
TodoList: это главный компонент, отображаемый в форме поля для ввода текста с самой обычной кнопкой. Все находится в форме, после отправки которой текст добавляется в список, поддерживаемый основным приложением. Код этого компонента очень прост:
import React, < Component >from 'react' class TodoList extends Component < render() < return ( ) > > export default TodoList
TodoItems: очень простой списковый компонент, используемый для вывода внутреннего списка элементов, добавленных через предыдущий компонент. Каждый из элементов кликабелен, и после нажатия на него он удаляется из списка. Код также весьма прост:
import React, < Component >from 'react' class TodoItems extends Component < createTasks(item) < return onClick= this.props.deleteItem(item.key)>> > render() < const todoEntries = this.props.entries || [] const listItems = todoEntries.map(this.createTasks.bind(this)) return > > export default TodoItems
В обоих случаях соответствующие методы принимаются как свойства (Props) из главного компонента App. Полный код этого компонента приведен здесь.
Согласен, это приложение очень простое, но, еще раз подчеркну, потенциально на его месте может быть любое приложение React, над которым вы работаете в настоящий момент – и внезапно получаете задачу приступить к миграции на TypeScript. Что же делать?
- Вариант #1: Утерев слезы, начинаете переписывать всю базу исходного кода.
- Вариант #2: Переименовываете все ваши файлы .js в .ts, настраиваете нужные шаги в сборочном процессе и умываете руки.
- Вариант #3: Вы решаете, что действительно пора перейти к постепенной миграции всего старого кода, а весь новый код писать уже непосредственно на TypeScript.
Вводим TypeScript
Итак, в качестве примера предположим, что нам поручено добавить кнопку-переключатель (toggle) к каждому компоненту в нашем списке дел. После нажатия на элемент его необходимо переключить в фоновом режиме.
Ничего сверхъестественного, но, как вы помните, нас в данном случае интересует процесс, а не код как таковой.
Итак, мы не будем пытаться добавлять TypeScript в уже имеющийся у вас настроенный проект, чтобы случайно не сломать имеющуюся у вас сборку на несколько жней, а создадим совершенно новый проект, воспользовавшись чистым TypeScript:
$ npx create-react-app ts-components --template typescript
Обратите внимание: для использования npx нужна только новая версия NPM, и она включается в процесс установки в версии 5.2.0 и выше.
Точно как и ранее, в таком случае создается шаблон для проекта, но на этот раз в качестве базового языка мы используем TypeScript.
Плюс простой компонент-переключатель, пригодный для вставки в другой проект, не привнося при этом дополнительных зависимостей. Если вам интересно, как это делается, почитайте следующую статью о том, как писать компоненты для многократного использования.
import React, from 'react'; interface IActionProps < action: (status:boolean) =>void, buttonText?: string > const Toggle = (: IActionProps) => < const [isSelected, setSelected] = useState(false) return ( < setSelected(!isSelected) action(isSelected) >> > ) > export default Toggle
Теперь, когда этот компонент написан, можно воспользоваться Bit (это опенсорсный инструмент для версионирования и публикации отдельных компонентов), чтобы извлечь данный конкретный компонент и поделиться им, чтобы впоследствии его можно было импортировать из нашего проекта, основанного на JavaScript.
// Устанавливаем Bit и инициализируем рабочее пространство в директории проекта $ yarn global add bit-bin $ bit init --package-manager yarn// входим в систему (после того, как создадим аккаует и коллекцию в bit.dev) $ bit login// добавляем все компоненты $ bit add src/components/Toggle.tsx // конфигурируем компоненты (чтобы открепить компоненты от env) $ bit import bit.envs/compilers/react-typescript --compiler// тегируем и экспортируем $ bit tag –all
Так вы сконфигурируете ваш проект и настроите в нем новый компонент Toggle (переключатель) таким образом, чтобы его можно было разделять с другими проектами. Но, прежде, чем сможете сделать это на практике, вам необходимо залогиниться в Bit.dev (это хаб компонентов — сайт с реестром и документацией, дополняющий Bit в качестве площадки для публикации и предварительного просмотра компонентов).
Войдя в систему, просто создайте новую коллекцию под названием “toggler”, сделайте ее публичной, а затем в окне терминала выполните следующую команду:
$ bit export user-name.toggler
Если “user-name” – действительно ваше имя пользователя, то в результате будет экспортирован компонент, и вы сможете увидеть его на Bit.dev. Он должен будет выглядеть примерно так:

Обратите внимание, как по умолчанию программа создает образец файла index.js , чтобы протестировать компонент. При этом, содержимое, записываемое в этот файл по умолчанию, может оказаться неидеальным, поэтому платформа позволяет с легкостью добавлять в него дополнительный код, благодаря которому другим станет понятно, как использовать ваш публичный компонент в своем коде.
Например, здесь я обновил мой файл-образец, добавив пояснения о том, как использовать компонент Toggler (только не забудьте нажать кнопку “Save”, когда закончите!):

Теперь давайте рассмотрим, как импортировать этот новый компонент в ваше собственное React-приложение на основе JS.
Импорт внешнего компонента
Bit берет на себя компиляцию вашего кода TypeScript в JavaScript благодаря добавленному нами компилятору. Это решает все наши проблемы, и все, что нам осталось – добавить этот компонент в ваш проект в качестве зависимости.
Для всех целей я использовал здесь Yarn, но вы с тем же успехом могли бы воспользоваться NPM, все, что для этого нужно:
$ yarn add @bit/your-username.your-collection.your-component
В моем случае этот код превращается в:
$ yarn add @bit/deleteman.toggler.toggle
Обратите внимание: вы не сможете устанавливать компоненты, не войдя в систему (помните часть о $ bit login в этом руководстве?). Если вы хотели бы установить компоненты из реестра Bit, то нужно сконфигурировать реестр вручную, вот так:
$ npm config set '@bit:registry' https://node.bit.dev
Таким образом ваш компонент TypeScript (уже скомпилированный в JavaScript) включится в проект, и вы сможете ссылаться на этот компонент их вашего кода следующим образом:
Обратите внимание на строку 2, где я импортирую внешний компонент, который собираюсь использовать в составе оператора возврата. Ничего сложного, не требуется вносить никаких дополнительных конфигурационных изменений ни в вашем проекте, ни где бы то ни было.
Поздравляю, теперь у вас есть рабочий проект, в котором используется как TypeScript, так и JavaScript, потенциально этого можно было сделать так, что вы бы этого даже не заметили!
Как я уже упоминал выше, полный код проекта выложен на GitHub!
Заключение
Если вас интересует миграция на TypeScript, либо вы просто хотите с ней поэкспериментировать и посмотреть, как она сработает, то именно таким образом удобно постепенно вводить язык в существующий проект, не рискуя обрушить весь процесс сборки.
Уделите внимание Bit и посмотрите Bit.dev, найдите там другие компоненты, написанные одновременно на JavaScript и TypeScript, чтобы понять, как их пишут другие!
- Блог компании Издательский дом «Питер»
- Занимательные задачки
- JavaScript
- Программирование
- TypeScript
Использование TypeScript¶
TypeScript — это язык, расширяющий JavaScript путем добавления определений типов. Новые проекты React Native по умолчанию используют TypeScript, но также поддерживают JavaScript и Flow.
Начало работы с TypeScript¶
Новые проекты, созданные с помощью React Native CLI или популярных шаблонов, таких как Ignite, по умолчанию будут использовать TypeScript.
TypeScript также можно использовать с Expo, который поддерживает шаблоны TypeScript или предложит вам автоматически установить и настроить TypeScript, когда файл .ts или .tsx будет добавлен в ваш проект.
npx create-expo-app --template
Добавление TypeScript в существующий проект¶
1. Добавьте TypeScript, типы и плагины ESLint в свой проект.
npm install -D @tsconfig/react-native @types/jest @types/react @types/react-test-renderer typescript
yarn add --dev @tsconfig/react-native @types/jest @types/react @types/react-test-renderer typescript
Эта команда добавляет последнюю версию каждой зависимости. Возможно, потребуется изменить версии, чтобы они соответствовали существующим пакетам, используемым в вашем проекте. Вы можете использовать такой инструмент, как React Native Upgrade Helper, чтобы посмотреть версии, поставляемые React Native.
2. Добавьте файл конфигурации TypeScript. Создайте tsconfig.json в корне вашего проекта:
1 2 3
"extends": "@tsconfig/react-native/tsconfig.json" >
3. Переименуйте файл JavaScript в *.tsx .
Вам следует оставить файл точки входа ./index.js как есть, иначе вы можете столкнуться с проблемой, когда дело дойдет до комплектации производственной сборки.
4. Запустите yarn tsc , чтобы проверить тип ваших новых файлов TypeScript.
Использование JavaScript вместо TypeScript¶
React Native по умолчанию устанавливает в новых приложениях TypeScript, но JavaScript все еще может использоваться. Файлы с расширением .jsx рассматриваются как JavaScript, а не TypeScript, и не будут проверяться. Модули JavaScript по-прежнему могут импортироваться модулями TypeScript, равно как и наоборот.
Как работает TypeScript и React Native¶
Исходные тексты TypeScript преобразуются Babel при компоновке. Мы рекомендуем использовать компилятор TypeScript только для проверки типов. Это поведение tsc по умолчанию для вновь создаваемых приложений. Если вы переносите существующий код TypeScript на React Native, есть одна или две оговорки в использовании Babel вместо TypeScript.
Как выглядит React Native + TypeScript¶
Вы можете предоставить интерфейс для Props и State React Component через React.Component , который обеспечит проверку типов и автозавершение редактора при работе с этим компонентом в JSX.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
import React from 'react'; import Button, StyleSheet, Text, View, > from 'react-native'; export type Props = name: string; baseEnthusiasmLevel?: number; >; const Hello: React.FCProps> = ( name, baseEnthusiasmLevel = 0, >) => const [ enthusiasmLevel, setEnthusiasmLevel, ] = React.useState(baseEnthusiasmLevel); const onIncrement = () => setEnthusiasmLevel(enthusiasmLevel + 1); const onDecrement = () => setEnthusiasmLevel( enthusiasmLevel > 0 ? enthusiasmLevel - 1 : 0 ); const getExclamationMarks = (numChars: number) => numChars > 0 ? Array(numChars + 1).join('!') : ''; return ( View style=styles.container>> Text style=styles.greeting>> Hello name> getExclamationMarks(enthusiasmLevel)> /Text> View> Button title="Increase enthusiasm" accessibilityLabel="increment" onPress=onIncrement> color="blue" /> Button title="Decrease enthusiasm" accessibilityLabel="decrement" onPress=onDecrement> color="red" /> /View> /View> ); >; const styles = StyleSheet.create( container: flex: 1, alignItems: 'center', justifyContent: 'center', >, greeting: fontSize: 20, fontWeight: 'bold', margin: 16, >, >); export default Hello;
Вы можете подробнее изучить синтаксис в TypeScript playground.
Где найти полезные советы¶
- Справочник по TypeScript
- документация React по TypeScript.
- React + TypeScript Cheatsheets содержит хороший обзор того, как использовать React с TypeScript.
Использование пользовательских псевдонимов путей с помощью TypeScript¶
Чтобы использовать пользовательские псевдонимы путей с TypeScript, необходимо настроить псевдонимы путей для работы как в Babel, так и в TypeScript. Вот как это сделать:
1. Отредактируйте ваш tsconfig.json , чтобы иметь ваши пользовательские сопоставления путей. Установите, чтобы все, что находится в корне src , было доступно без предшествующей ссылки на путь, и разрешите доступ к любому тестовому файлу с помощью tests/File.tsx :
1 2 3 4 5 6 7 8 9 10 11 12
< - "extends": "@tsconfig/react-native/tsconfig.json" + "extends": "@tsconfig/react-native/tsconfig.json", + "compilerOptions": + "baseUrl": ".", + "paths": + "*": ["src/*"], + "tests": ["tests/*"], + "@components/*": ["src/components/*"], + >, + > >
2. Добавьте babel-plugin-module-resolver в качестве пакета разработки в свой проект:
Настройка TypeScript для React и JSX
Из-за природы JSX, чтоб TypeScript и React отлично сочетались друг с другом, для этого потребуется немного настроить сам TypeScript .
TypeScript · 04.10.2019 · читать 2 мин · Автор: Alexey Myzgin
TypeScript и React отлично сочетаются друг с другом, но для этого требуется немного настроить TypeScript из-за природы JSX. Опция компилятора для JSX просто должна быть настроена на “react” в tsconfig.json .
Чтобы использовать TypeScript с React — изменим расширение c ts на tsx index.ts файл, а также сделаем изменения в index.html . В index.html добавим место, где будет наше React приложение .
DOCTYPE html> html lang="en"> head> meta charset="UTF-8" /> meta name="viewport" content="width=device-width, initial-scale=1.0" /> meta http-equiv="X-UA-Compatible" content="ie=edge" /> title>Documenttitle> head> body> div id="app">div> body> script src="./index.tsx"> script> html>
Затем в index.tsx быстро создадим React приложение:
import React from "react"; import render > from "react-dom"; class App extends React.Component render() return div>Hidiv>; > > render(App />, document.getElementById("app"));
Для сборки проекта мы используем parcel bundler. Как только мы запустим parcel index.html , увидим, что parcel сам установит React и необходимые зависимости автоматически.
Если мы откроем сервер — http://localhost:1234/ — у нас в консоле будет ошибка ReferenceError: React is not defined . Это можно исправить, изменив способ импорта React, сказав import * as React from «react» . Из-за небольшого различия между тем, как JavaScript и TypeScript принимают этот импорт по умолчанию.
Если ты хочешь сохранить импорт по умолчанию, нужно создать то, что называется tsconfig.json , который содержит конфигурацию для компилятора. Создадим его в корне нашего проекта со значениями:
"compilerOptions": "jsx": "react" > >
Затем нужно будет остановить сборку, удалить кеш (там есть скрытый каталог с файлами parcel) и затем перезапустить parcel, чтобы он принял изменения конфигурации.
rm -rf .cache
parcel index.html
Если ты используешь текстовый редактор VS Code, то есть ещё одна вещь, на которую стоит обратить внимание, — это три крошечные точки возле импорта react и react-dom , которые говорят о том, что мы можем нажать Command + . , чтобы выполнить предлагаемые действия из VS Code.
VS Code предлагает установить отсутствующие пакеты типов, потому что типы для React и ReactDOM размещаются в организации @types на NPM. Мы автоматически добавим @types/react и @types/react-dom в наши зависимости.
npm i @types/react @types/react-dom
У нас особо ничего не поменялось, только теперь нужно добавить в tsconfig.json новое значение allowSyntheticDefaultImports , так как TypeScript выдает ошибку на импорт React: This module is declared with using ‘export =’, and can only be used with a default import when using the ‘esModuleInterop’ flag. . Для этого нам нужно добавить allowSyntheticDefaultImports со значением true :
"compilerOptions": "jsx": "react", "allowSyntheticDefaultImports": true > >
Если попытаемся сделать что-то недопустимое, например: в классе после render ничего не вернуть, то ошибка будет ещё до компиляции. По сути, это говорит, что нам нужно вернуть что-то из render .
как подключить typescript к react
Для подключения TypeScript к React необходимо выполнить следующие шаги:
- Установить TypeScript и ts-loader:
install typescript ts-loader --save-dev
- Создать файл tsconfig.json в корневой директории проекта и описать правила. Пример:
"compilerOptions": "outDir": "./dist/", "module": "es6", "target": "es5", "jsx": "react", "allowJs": true >, "include": ["./src/**/*"] >
Этот файл определяет настройки компилятора TypeScript и указывает, где находятся файлы проекта.
- Создать webpack.config.js файл:
const path = require('path'); module.exports = entry: './src/index.tsx', module: rules: [ test: /\.tsx?$/, loader: 'ts-loader', exclude: /node_modules/, >, ], >, resolve: extensions: ['.tsx', '.ts', '.js'], >, output: filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), >, >;
Этот файл определяет настройки Webpack.
- Создать файл index.tsx в папке src и добавить в него следующий код:
import React from 'react'; import ReactDOM from 'react-dom'; interface AppProps message: string; > const App: React.FCAppProps> = ( message >) => return h1>message>h1>; >; ReactDOM.render( App message='Hello, world!' />, document.getElementById('root') );
Этот файл определяет основной компонент React.
- Создать файл index.html в корневой директории проекта и добавить в него следующий код:
charset="utf-8" /> React TypeScript id="root">