Writing Vue.js Components with Flow

Joshua Bemenderfer

Type checking is a tricky concept in Vue. While it’s easy to do in plain script files, Vue single-file components are a much trickier beast to get working. While some choose TypeScript, perhaps for class-based components, others find TypeScript’s heavyweight nature and difficulty to integrate with common tools to not be worth the effort. Facebook’s Flow is a typechecker that fits much better into a standard webpack + babel + eslint toolchain, and is commonly used in React projects. Once you get it set up, it just works!

Getting Flow to work with Vue is a bit tricky as it involves several dependencies and minor configuration tweaks to make them all work properly together, so let’s start out by installing those first.

Installation

Starting from vue-cli’s webpack-simple template, there are nine extra dependencies to install. Here’s what each of them does:

Babel:

  • babel-plugin-syntax-flow - Adds support for flow syntax in Babel.
  • babel-plugin-transform-class-properties - Adds support for class properties and static methods
  • babel-plugin-transform-flow-strip-types - Removes type annotations from source files before transpiling with Babel.

Eslint: (optional)

  • eslint - Eslint. It’s pretty much the de-facto linter for JS, with integrations for a variety of editors and IDEs as well. If you’re not using this now, you’ll want to start using it.
  • babel-eslint - Patches Eslint to use Babel’s parser for parsing source files.
  • eslint-plugin-html - Allows Eslint to handle HTML files. (ie. Only lints stuff inside script tags.)
  • eslint-plugin-flowtype-errors - Passes flow errors through Eslint, and to your editor’s eslint plugin if you have one.
  • eslint-plugin-vue - Opinionated utilities for Eslint with Vue.
  • eslint-config-vue - Opinionated config for Eslint with Vue.

Flow:

  • flow-bin - The Flow typechecker.

Install via Yarn or NPM:

# Yarn
$ yarn add \
  babel-plugin-syntax-flow \
  babel-plugin-transform-class-properties \
  babel-plugin-transform-flow-strip-types \
  eslint \
  babel-eslint \
  eslint-plugin-html \
  eslint-plugin-flowtype-errors \
  eslint-plugin-vue \
  eslint-config-vue \
  flow-bin \
-D

# NPM
$ npm install \
  babel-plugin-syntax-flow \
  babel-plugin-transform-class-properties \
  babel-plugin-transform-flow-strip-types \
  eslint \
  babel-eslint \
  eslint-plugin-html \
  eslint-plugin-flowtype-errors \
  eslint-plugin-vue \
  eslint-config-vue \
  flow-bin \
--save-dev

Configuration

.babelrc

Add the babel plugins to the end of your .babelrc file.

{
  ...
  "plugins": [
    "babel-plugin-transform-class-properties",
    "babel-plugin-syntax-flow",
    "babel-plugin-transform-flow-strip-types"
  ]
}

.eslintrc

Set up your .eslintrc file like so:

{
  "parser": "babel-eslint",

  "plugins": [
    "html",
    "flowtype-errors"
  ],

  "extends": [
    "vue"
  ],

  "rules": {
    "flowtype-errors/show-errors": 2
  }
}

.flowconfig

And finally, create a .flowconfig file in your project root directory. It can be empty, just make sure it’s present.

Usage

You can now use Flow in your .js files or .vue single-file components just by adding the /* @flow */ annotation to the top of each file or script section.

Assuming your editor or IDE has the proper eslint packages installed, you should now have real-time error checking and positional annotations whenever there is an error or warning.

stupid-file.js

/* @flow */

const doSomethingStupid(stringArg) {
  // Flow should show an error here, "The operand of an arithmetic operation must be a number."
  return stringArg * 3109;
}

console.log(doSomethingStupid(`I'm stringy`))

ExampleComponent.vue

<template>
  <p>I'm made with Flow!</p>
</template>

<script>
/* @flow */

const randomThing: string = 'Boop!'

export default {
  created() {
    console.log(randomThing)
  }
}
</script>

And there you have it! Nothing else in your toolchain has to change.

There's plenty more to learn about Flow. If you're not familiar with it already, a great next step would be the Flow Docs. Enjoy!

  Tweet It
✖ Clear

🕵 Search Results

🔎 Searching...