Skip to content

Latest commit

 

History

History
 
 

12-flow

12 - Flow

Flow - статический типизатор (static type checker). Он определяет несоответствие типов в вашем коде и позволяет напрямую декларировать типы через аннотации.

  • Для того, чтобы Babel мог понимать и убирать аннотации Flow в процессе транспиляции, установите плагин Flow для Babel, выполнив yarn add --dev babel-preset-flow. Затем добавье "flow" после babel.presets в package.json.

  • Создайте пустой файл .flowconfig в корне проекта.

  • Запустите yarn add --dev gulp-flowtype, чтобы установить Gulp плагин для Flow, и добавьте flow() в задачу lint:

import flow from 'gulp-flowtype';

// [...]

gulp.task('lint', () =>
  gulp.src([
    paths.allSrcJs,
    paths.gulpFile,
    paths.webpackFile,
  ])
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failAfterError())
    .pipe(flow({ abort: true })) // Add Flow here
);

Опция abort прерывает задачу Gulp, если Flow обнаруживает проблему.

Отлично, теперь мы можем запустить Flow.

  • Добавьте аннотации Flow в src/shared/dog.js так, чтобы:
// @flow

class Dog {
  name: string;

  constructor(name: string) {
    this.name = name;
  }

  bark(): string {
    return `Wah wah, I am ${this.name}`;
  }

  barkInConsole() {
    /* eslint-disable no-console */
    console.log(this.bark());
    /* eslint-enable no-console */
  }

}

export default Dog;

Комментарий // @flow говорит Flow, что мы хотим проверять типы для этого файла. Сами аннотации Flow предваряются двоеточием и обычно добавляются после параметра функции или имени функции. Подробности смотрите в документации.

Теперь, если вы запустите yarn start, Flow будет работать, но ESLint начнет жаловаться, что используется нестандартный синтаксис. Поскольку парсер Babel отлично справляется с парсингом Flow контента (благодаря установленному нами плагину babel-preset-flow), было бы здорово, если бы ESLint мог опираться на парсер Babel, вместо того, чтобы пытаться самому понять аннотации Flow. Это возможно при использовании пакета babel-eslint. Давайте сделаем это.

  • Запустите yarn add --dev babel-eslint

  • В package.json, после eslintConfig, добавьте следующее свойство: "parser": "babel-eslint"

Теперь yarn start должен одновременно анализировать код с помощью ESLint и проверять типы посредством Flow.

Далее, поскольку ESLint и Babel совместно используют общий парсер, мы можем заставить ESLint проверять наши Flow аннотации, используя плагин eslint-plugin-flowtype.

  • Запустите yarn add --dev eslint-plugin-flowtype и добавьте "flowtype" после eslintConfig.plugins в package.json. Затем добавьте "plugin:flowtype/recommended" после eslintConfig.extends в массив после "airbnb".

Теперь, если вы, например, введете name:string в качестве аннотации, ESLint должен пожаловаться, что вы забыли пробел после двоеточия.

Примечание: Свойство "parser": "babel-eslint", которое я заставил вас написать в package.json, вообще-то входит в конфигурацию "plugin:flowtype/recommended", так что теперь можете убрать его, чтобы сократить package.json. С другой стороны, оставить его здесь будет более наглядным, так что это на ваше усмотрение. Поскольку это руководство нацелено на максимальную краткость, я его уберу.

  • Теперь вы можете добавить // @flow в каждый .js и .jsx файл в папке src, запустить yarn test или yarn start, и добавлять аннотации везде, где этого попросит Flow.

Вы можете обнаружить неожиданный пример в src/client/components/message.jsx:

const Message = ({ message }: { message: string }) => <div>{message}</div>;

Как вы видите, при деструктурировании параметра функции, необходимо делать аннотации для выделяемых свойств в виде объекта в литеральной нотации.

Другой случай, с которым вы столкнетесь, будет в src/client/reducers/dog-reducer.js. Flow начнет жаловаться, что Immutable не имеет возвращаемого значения по умолчанию. Эта проблема описана тут: #863 on Immutable, и имеет два обходных пути:

import { Map as ImmutableMap } from 'immutable';
// или
import * as Immutable from 'immutable';

Пока Immutable официально не решит проблему, просто выберите то, что вам больше нравится, когда импортируете компоненты Immutable. Лично я, буду использовать import * as Immutable from 'immutable', поскольку это короче и не потребует рефакторинга кода, после того, как проблема будет решена.

Примечание: Если Flow выявляет ошибки типизации в папке node_modules, добавьте раздел [ignore] в файл .flowconfig, чтобы указать какие именно пакеты игнорировать (не игнорируйте полностью директорию node_modules). Это может выглядеть так:

[ignore]

.*/node_modules/gulp-flowtype/.*

В моем случе, плагин linter-flow для Atom обнаружил ошибки типизации в директории node_modules/gulp-flowtype, которая содержит файлы аннотированные // @flow.

Теперь, у вас есть "пуленепробиваемый" код, который проанализирован, протипизирован и протестирован - отличная работа!

Назад в предыдущий раздел или Содержание.