How to get Flow to properly work with Vue 2 (webpack)? How to get Flow to properly work with Vue 2 (webpack)? vue.js vue.js

How to get Flow to properly work with Vue 2 (webpack)?


Using eslint + flow

This is yet another approach to integrating flow & vue.Meanwhile, flow came to eslint. Therefore, we can get flow errors straight as lint errors. It's a cleaner approach, but then flow becomes coupled with your build process (you can't run flow check independently, but need to run your entire build pipeline via webpack to get the errors). Still waiting for this issue to be resolved to have full flow support in .vue files as of 10th of May 2017.

For most cases that's fine, but some might still want the flexibility (and speed) of running flow check. That might also depend on your CI setup.

Here's how you can setup flow and eslint:

  1. Install deps

    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
  2. Configure .babelrc

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

    {  "parser": "babel-eslint",  "plugins": [    "html",    "flowtype-errors"  ],  "extends": [    "vue"  ],  "rules": {    "flowtype-errors/show-errors": 2  }}
  4. Create a .flowconfig file. It can be empty if you have nothing to configure.

No other workarounds required in this case, you can then just use /* @flow */ in the script tags in any of your .vue files.See the original post here.


You can still use Flow for the JS portion of a .vue component, by commenting out the <template>, <style> and <script> portions:

 /* @flow <style> ...style definitions here </style> <template> ...html... </template> */ // <script> export default {     methods: {      flowIt (a: number): number {         return a * 10      }   },   mounted: function () {      this.flowIt(20)      this.flowIt('bah') //Won't throw error, as flowIt is attached to                         //this.   }}// </script>

The vue compiler will still recognize the <template>, <style> and <script> sections even when commented, but the Flow type checker will ignore them and only process the proper javascript section.

Unfortunately, this won't get you 100% type coverage, as Flow will not be able to check functions and objects attached to this (the Vue component itself), however, you can still benefit from Flow's type checking of calls out to external functions (e.g. Vuex actions and getters, other javascript imported modules), and if you have extended business logic within the component's methods, you can get some type safety when working with the method parameters.


In addition to Nik's answer, it's worth mentioning that combining his 'comment' strategy with a runtime checker makes 'the package' a tad more complete. One way to do it is by using babel-plugin-tcomb. That'll make the runtime checker part of the webpack / build process (on save) + flow check as part of a CI script.

For development, tcomb will do a runtime check and will throw an exception (console). It doesn't do static checks, so the following

<script>/* @flow */const flowIt = (a: number): number => {  return '' // Sees nothing wrong here, should be a number}// Vue componentexport default {      ...}</script>

won't work as expected. However, the following will:

<template>{{ foo('bar') }} <!-- Type error --></template><script>/* @flow */const flowIt = (a: number): number => {  return '' // Type error}// Vue componentexport default {      methods: {    foo: (x) => { flowIt(x) // Type error }  },  mounted: () => {    flowIt([]) // Type error  }}</script>

That's not ideal, but it does check after each save and that'll catch most type errors.Worth mentioning: tcomb uses the same annotations (uses Flow internally), so it works out of the box.

Ofc, that's not good enough & kinda defeats the point of Flow. The solution to that is to still run flow check on the CI, as mentioned. That requires a number of changes:

  1. Update .flowconfig to load .vue files:

    ...[options]module.file_ext=.vuemodule.file_ext=.js...
  2. Include the template & style block in the comment containing the @flow pragma; comment out the script tags (this approach was mentioned here):

    /* @flow<template>...</template><style>...</style>*/// <script>...// </script>

    That's a bit awkward, but I could not find a better way. Ideally, Flow would be able to process <script> tags in a HTML doc, but that's just on the wishlist for now (see issue).

  3. Disable tcomb in production

    {  ...  "plugins": [    ...    "syntax-flow",    "transform-flow-strip-types"  ],  "env": {    "development": {      "plugins": ["tcomb"]    }  }}