В моих приложениях React/JavaScript есть три уровня «безопасности» разработки, которые я всегда добавляю:
- ESLint, чтобы убедиться, что код соответствует определенному стандарту
- Модульное тестирование, чтобы убедиться, что коды можно тестировать
- Статическая типизация, чтобы добавить ясности и уменьшить путаницу
В этой статье я расскажу, как начать использовать статическую типизацию с Flow в приложениях React.
Есть несколько технологий, которые мы можем использовать для добавления статической типизации в JavaScript, наиболее популярным из которых является TypeScript (TS). Он разработан Microsoft в 2012 году и имеет большое сообщество. Все основные интерфейсные библиотеки, такие как Angular, Vue и React, поддерживают TS.
Но лично я предпочитаю Flow, а не TS. Flow разработан Facebook в 2014 году. Вот (вероятно, субъективные) причины, по которым мне больше нравится Flow:
- Он разработан Facebook (который разработал React, мою любимую библиотеку интерфейса). Поэтому, естественно, React лучше работает с Flow.*
- Чтобы сделать JS-файл для использования Flow, я просто добавляю одну строку поверх файла (
//@flow
). Расширение файла по-прежнему будет.js
. - TS — это совершенно новый язык с собственным расширением файла (
.ts
). В то время как Flow — это скорее инструмент проверки типов, который вы применяете в своих JS-приложениях. Вроде как ESLint imo. - Поскольку TS — совершенно новый язык, у него более высокая кривая обучения.
- Гораздо проще преобразовать код JS с помощью Flow обратно в чистый JS.
- Вы можете легко интегрировать Flow в существующее приложение JS.
- Flow просто проще.
*Однако для приложений Node я больше склоняюсь к TS
На самом деле, если вы напишете файл длиной в 10 000 строк без каких-либо внешних зависимостей, без каких-либо типов. Flow по-прежнему сможет указать вам, где находятся ошибки.
— Джеймс Кайл, член команд Babel и Flow.
В этом примере я буду использовать шаблон приложения React, описанный в моей предыдущей статье. Я объясню все конфигурации, которые я добавил в этот шаблон приложения React.
Установка Flow и вспомогательных библиотек
Очевидно, нам сначала нужно установить Flow. И поскольку мы используем Flow в приложении React, которое использует Babel для компиляции, нам также нужно добавить несколько других библиотек.
// install Flow npm install --save-dev flow-bin // install Babel support for Flow npm install --save-dev @babel/preset-flow babel-plugin-transform-flow-strip-types
После добавления этих библиотек нам нужно включить некоторые из них в файл .babelrc
. Вот дополнительные строки:
{ "presets": [ ..., "@babel/preset-flow" ], "plugins": [ ..., "transform-flow-strip-types" ] }
Запуск Flow-сервера
Прежде чем мы сможем запустить сервер Flow, нам нужно его инициализировать и настроить. Сначала запустите эту команду:
npm run flow init
Эта команда приведет к созданию пустого файла .flowconfig
. Это конфигурация, которую я использую в своем примере приложения.
[ignore] .*/node-modules/.* [include] ./src [libs] [lints] [options] react.runtime=automatic [strict]
Подробнее о том, как настроить Flow, вы можете прочитать в этой статье.
Чтобы запустить сервер Flow, сначала я добавляю этот скрипт на package.json
:
"scripts": { ..., "flow": "flow", "flow-stop": "flow stop" },
Затем в консоли просто введите npm run flow
, чтобы запустить фоновый процесс сервера Flow. Эта команда покажет на консоли все ошибки, связанные со статическим типом; которых на данном этапе, вероятно, нет.
Используйте npm run flow-stop
, если вы хотите остановить фоновый процесс сервера Flow.
Добавление поддержки Flow в IDE
Я использую Visual Studio Code от Microsoft в качестве своей IDE, поэтому приведенный ниже пример относится только к этому VSCode.
- Установите плагин Flow Language Support от flowtype.
- Отключите встроенную поддержку TypeScript в VSCode.
Встроенная поддержка TS может конфликтовать с плагином Flow. Вы можете найти этот плагин, набрав `@builtin TypeScript` на вкладке «Расширения» в VSCode. Как только вы его нашли, отключите плагин.
Проверьте здесь для получения дополнительной информации.
Добавление статической проверки типов Flow
Чтобы добавить поддержку статического типа, просто добавьте этот код в первую строку любого JS-файла:
// @flow
Вот и все!
Добавляя эту строку, вы можете постепенно внедрять Flow и легко удалить ее в любое время. Вы можете попробовать Flow out на любой кодовой базе и посмотреть, понравится ли вам это.
Изучите файл 002-react-flow/src/someMethods.js
в примере, чтобы увидеть простой файл JavaScript со статическим типом.
Использование Flow на компонентах React
Я не буду обсуждать типовые аннотации во Flow, потому что по этому поводу уже есть много документации и статей. Кроме того, аннотации Flow в основном очень похожи на некоторые аннотации, используемые в TS или любых языках программирования со статической типизацией. Вместо этого я буду обсуждать аннотации, специально используемые для компонентов React.
Реагировать Компонент
Нам нужно импортировать тип React, который мы используем, в компонент. Поскольку обычно компонент React возвращает Node
, нам нужно убедиться, что он импортирован.
import type {Node} from "react";
Компонент обычно принимает свойства. Допустим, у компонента есть два свойства: foo
и bar
. В Flow мы определяем эти свойства следующим образом:
type Props = { foo: number, bar?: string };
Если компонент использует state
, нам также необходимо определить его:
type State = { count: number, };
Затем нам нужно аннотировать эти определения в компоненте:
class SimpleComponent extends Component<Props, State> { ...
И, наконец, в методе render()
мы должны добавить аннотацию возвращаемого типа:
render(): Node { ...
Это полный код для этого примера компонента:
// @flow import type {Node} from "react"; import React, {Component} from 'react'; type Props = { foo: number, bar?: string, }; type State = { count: number, }; class SimpleComponent extends Component<Props, State> { constructor() { super(); this.state = { count: 0, } } componentDidMount() { setInterval(() => { this.setState(prevState => ( { count: prevState.count + 1 } )); }, 1000); } render(): Node { return ( <div> {this.props.foo} {this.props.bar} <br/> Count: {this.state.count} </div> ); } } export default SimpleComponent;
Функциональный компонент React
В основном аналогично предыдущему примеру, но с немного другим синтаксисом. Обратите внимание, что здесь мы не расширяем объект Component
. И мы объявляем типы свойств в параметре функции.
// @flow import type {Node} from "react"; import React from 'react'; type Props = { text: string, addExclamMark: boolean, }; const SimpleFuncComponent = ({text, addExclamMark}: Props): Node => { return ( <div> {`${text}${addExclamMark ? '!' : ''}`} </div> ) }; export default SimpleFuncComponent;
Вывод
Да, у TS гораздо большее сообщество. Но нет ничего необычного в том, чтобы выбрать технологию, которая лучше подходит вашему стилю/среде разработки. В моем случае Flow оказался лучшим вариантом (при разработке приложений React). Опять же, это субъективное мнение. Возможно, в будущем я передумаю, кто знает. Но на данный момент мне гораздо удобнее использовать Flow. И я знаю некоторые организации, которым удобно вообще не использовать статическую типизацию в своих JS-приложениях.
Наконец, я предоставил полный пример приложения React на своем Github. Если у вас возникли проблемы с прочтением статьи или запуском примера приложения, или у вас есть какие-либо вопросы, пожалуйста, упомяните меня в Твиттере. Ваше здоровье!