Поток и реакция

Когда дело доходит до линтинга статических типов Javascript, машинописный текст более популярен, чем поток на рыночной доле. Однако сообщество Flow за последний год выросло в геометрической прогрессии благодаря недавним улучшениям. Поскольку и Flow, и React принадлежат одному сообществу, они прекрасно подходят друг другу.

Предполагая, что вы понимаете преимущества использования статических типов в вашем Javascript, Flow прекрасно справляется с постепенным добавлением типов в ваше приложение. Если вам интересно, каковы преимущества статических типов в Javascript, вот отличный доклад на React Conf 2017 на эту тему.

Поток против машинописного текста

Оба варианта - отличные, у каждого есть свои плюсы и минусы. Как упоминалось выше, популярность Flow растет и в него добавляются дополнительные функции для повышения совместимости.

Снимок. Flow определяет типы с самого начала, в то время как TypeScript проверяет только то, что ему предоставлено. Это означает, что с самого начала Flow проверяет больше типов. По незнанию можно легко пропустить предоставление типов через Typescript. Конечно, в Flow все еще можно злоупотреблять типом any, но для этого нужно быть более явным. Кроме того, для запуска потока требуется небольшое количество настроек.

Моя любимая статья на эту тему написана Джеймсом Кайлом. Вот изображение из его статьи, которое показывает проверку типов между потоком и машинописным текстом.

Добро

Реагировать:

  • Простая установка - все, что требуется - это плагин babel. Также использует файл .flowconfig.
yarn add --dev babel-cli babel-preset-flow
----------------------------
flow init
----------------------------
// babelrc
{
  "presets": ["flow"]
}
----------------------------
/// package.json
"scripts": {
  "flow": "flow"
}
  • Мгновенная проверка типа (если применимо)
  • Можно заменить пакет prop-types npm (без предупреждений в консоли во время выполнения, если отсутствует тип пропуска)
type Props = {
  foo: number,
  bar?: string, // replicates a notRequired flag
};

class MyComponent extends React.Component<Props> {
  render() {
    this.props.doesNotExist; 

    return <div>{this.props.bar}</div>;
  }
}

<MyComponent foo={42} />;
  • Проверки типов для локальных объектов состояния компонентов
type Props = { /* ... */ };

type State = {
  count: number,
};

class MyComponent extends React.Component<Props, State> {
  state = {
    count: 0,
  };
...
}
  • Тип Проверяет свойства по умолчанию - их можно вставить в компонент с помощью ‹› после React.Component.
  • Типы могут быть добавлены как к классовым, так и к функциональным компонентам.
type Props = {
  foo: number,
  bar?: string,
};

function MyComponent(props: Props) {
  props.doesNotExist; // Error! You did not define a `doesNotExist` prop.

  return <div>{props.bar}</div>;
}
  • Обрабатывает синтетические события с SyntheticEvent ‹T›
class MyComponent extends React.Component<{}, { count: number }> {
  handleClick = (event: SyntheticEvent<HTMLButtonElement>) => {
    // To access your button instance use `event.currentTarget`.
    (event.currentTarget: HTMLButtonElement);

    this.setState(prevState => ({
      count: prevState.count,
    }));
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.handleClick}>
          Increment
        </button>
      </div>
    );
  }
}
  • Можно установить лимит потомков, унаследованных через компоненты, используя тип props:
type Props = {
  children: React.Element<any>,
};

Redux:

  • Проверка типа для состояния редуктора - может использоваться для селекторов и начального состояния
type State = {
  +users: Array<{
    +id: string
    +name: string,
    +age: number,
    +phoneNumber: string,
  }>,
  +activeUserID: string,
  // ...
};
  • Проверка типа для действий
type Action = {
  +type: string,
};
type FooAction = { type: "FOO", foo: number };
type BarAction = { type: "BAR", bar: boolean };

type Action =
  | FooAction
  | BarAction;
  • Не портит тесты Mocha / Jest
  • Поддержка функций генератора (асинхронные задачи)

Общие:

  • Можно установить определенные типы, например 3 или "Money"
  • ... остальное / спред принято
  • Точные типы объектов. Иногда полезно отключить это поведение и разрешить только определенный набор свойств. Для этого Flow поддерживает «точные» типы объектов.
{| foo: string, bar: number |}

В отличие от обычных типов объектов, нельзя передавать объект с «дополнительными» свойствами конкретному типу объекта.

// @flow
var foo: {| foo: string |} = { foo: "Hello", bar: "World!" }; // Error!

Плохо

Реагировать:

  • Не поддерживает декораторы (но необходимо добавить параметр игнорирования в файл flowconfig). Что продвигает ожидания, что любые ранние предложения TC39 должны быть подтверждены в потоке перед использованием.
  • Некоторые модули узлов выдают ошибки, поэтому их нужно игнорировать по отдельности или предоставить обходные пути. Невозможно игнорировать всю папку node_modules, потому что пакеты проверяются при использовании в проекте.
  • Код, вызывающий ошибки времени выполнения, не будет перехвачен потоком (не только для потока)
  • Eslint не любит, когда в файле присутствуют «неопределенные» типы, такие как HTMLTableRowElement (Решение, определить как глобальные в rc файле)

Redux:

  • Нет прямых примеров использования Flow с функциями саги / генератора. (Есть примеры функций генератора, но они не прямолинейны.

Заключение

Несмотря на то, что его относительно легко установить и начать работу над проектом, мне потребовалось немного времени, чтобы настроить некоторые параметры приложения. Были некоторые конфликтующие пакеты и ошибки исключения, которые необходимо было исправить. Однако, как только я прошел через них, это стало легко реализовать как в React, так и в Redux.

TypeScript более популярен с точки зрения использования во всем мире и в пакетах npm. Однако с появлением некоторых последних выпусков Flow он набирает популярность. У Flow отличное сообщество, и с такими инструментами, как flow-upgrade, можно легко увеличить любой проект.

flow-upgrade - это утилита, позволяющая сделать обновление при критических изменениях в Flow гораздо менее болезненным. flow-upgrade - это тот же самый инструмент, который мы используем для обновления нашего кода внутри Facebook, и он доступен как модуль npm, который может использовать каждый.

Дополнительные ссылки:

Подпишись на меня в Твиттере! @iamtylerwclark