JS static type checking tool Flow

JS static type checking tool Flow

This article mainly introduces the static type checking tool Flowthat solves the pain points of JS as a weakly typed language without type checking , and introduces the method of using Flow in WebStorm, and finally introduces some commonly used Flow syntax.

1 Introduction

JS, as a scripting language, has no type detection. This feature is sometimes very convenient to use, but in a larger project you will find that this is actually a very bad feature, because the programmers you collaborate with are often It's not clear which type of code you are writing is correct, and it will be more troublesome to wait until the code is refactored. So based on this demand, Typescript and Flow were produced, which are mainly introduced here today Flow.

Flow is a JavaScript static type checking tool produced by Facebook. It is different from Typescript in that it can be partially imported without completely refactoring the entire project. Therefore, for a project with a certain scale, the migration cost is smaller. It is also more feasible. In addition, Flow can provide real-time incremental feedback. By running the Flow server, there is no need to completely re-run the type check every time a project is changed, thereby improving operating efficiency. Both Flow and Typescript are excellent solutions for adding type checking to Javascript. A simple comparison of the two is as follows:

tool

Flow

TypeScript

the company

Facebook

Microsoft

star

16k

33k

Document support level

medium

many

advantage

High degree of freedom, low migration cost of old projects

Strong engineering, active community, high official support

The difference between the two usage scenarios can be briefly summarized as follows: For new projects, you can consider using TypeScript or Flow. For projects with a certain scale, it is recommended to use Flow for a gradual migration with a smaller cost to introduce type checking. Flow can help find errors caused by unreasonable type operations, including operator operations, function parameter types, and return value types. Flow also supports type language-related operations such as custom type declarations and generic declarations. For details, please refer to the documentation .

Introduction method: added at the beginning of type checking requires Flow js file //@flowor /* @flow */, Flow can be introduced, a simple example:

//@flow
function square(n: number): number {
  return n * n;
}

square("2");//Error!

2. Installation method

npm installation:

npm install --save-dev babel-cli babel-preset-flow flow-babel-webpack-plugin babel-preset-es2015 babel-preset-env babel-plugin-transform-class-properties

I installed it globally:

npm install -g babel-cli babel-preset-flow flow-bin flow-babel-webpack-plugin babel-preset-es2015 babel-preset-env babel-plugin-transform-class-properties

.babelrcAdd in the file:

{
  "presets": ["flow", "es2015"],
  "plugins": [
    "transform-vue-jsx",
    "transform-runtime",
    "transform-class-properties"
  ]
}

Set about WebStorm: by File>Settings>Languages&Frameworks>JavaScriptselecting Flow, Flow package can select flow-bin under your project, but you can also install a global flow-bin, then after a set here can use Flow in each project. But flow cannot be used directly in the node or browser environment, so we must use babel to compile it before it can be used. Use File watcher:

Run in the project directory flow init, it will automatically generate a file .flowconfig, this file can configure flow, my configuration:

[ignore]
.*/node_modules/.*
<PROJECT_ROOT>/build/.*
<PROJECT_ROOT>/config/.*

[options]
module.file_ext=.js
module.file_ext=.vue

Now when we use Flow in our project, WebStorm can give intelligent prompts.

And there is an additional window Flow that gives all the prompts in the document:

3. Use

The latest ECMAScript standard defines 7 data types: 6 primitive types: Boolean, Null, Undefined, Number, String, Symbol and Object

These types are also used as annotations in Flow:

Use primitive types:

//@flow
function method(x: number, y: string, z: boolean) {
 //...
}

method(3.14, "hello", true);

Use object type:

//@flow
function method(x: Number, y: String, z: Boolean) {
 //...
}

method(new Number(42), new String("world"), new Boolean(false));

What needs to be noted here is the capitalization, the lowercase number is the primitive type, and the uppercase Number is the JavaScript constructor, which is the object type.

Boolean

In Flow, the type is not converted by default. If you need to convert the type, please use explicit or implicit conversion, for example:

//@flow
function acceptsBoolean(value: boolean) {
 //...
}

acceptsBoolean(true);//Works!
acceptsBoolean(false);//Works!
acceptsBoolean("foo");//Error!
acceptsBoolean(Boolean("foo"));//Works!
acceptsBoolean(!!("foo"));//Works!

Number

//@flow
function acceptsNumber(value: number) {
 //...
}

acceptsNumber(42);//Works!
acceptsNumber(3.14);//Works!
acceptsNumber(NaN);//Works!
acceptsNumber(Infinity);//Works!
acceptsNumber("foo");//Error!

null and void

JavaScript has both null and undefined. Flow treats these as separate types: null and void (void means undefined type)

//@flow
function acceptsNull(value: null) {
 /* ... */
}

function acceptsUndefined(value: void) {
 /* ... */
}

acceptsNull(null);//Works!
acceptsNull(undefined);//Error!
acceptsUndefined(null);//Error!
acceptsUndefined(undefined);//Works!

Maybe type

Maybe types are used for optional values. You can create them by adding a question mark (such as ?string or ?number) before the type.

In addition to the type followed by the question mark?, perhaps the type can also be a null or void type.

//@flow
function acceptsMaybeString(value: ?string) {
 //...
}

acceptsMaybeString("bar");//Works!
acceptsMaybeString(undefined);//Works!
acceptsMaybeString(null);//Works!
acceptsMaybeString();//Works!

Optional object attributes

Object types can have optional attributes, and the question mark? Is located after the attribute name.

{propertyName?: string}

In addition to their set value types, these optional attributes can also be completely omitted by void. However, they cannot be null.

//@flow
function acceptsObject(value: {foo?: string }) {
 //...
}

acceptsObject({ foo: "bar" });//Works!
acceptsObject({ foo: undefined });//Works!
acceptsObject({ foo: null });//Error!
acceptsObject({});//Works!

Optional function parameters

Functions can have optional parameters, where the question mark? appears after the parameter name. Similarly, this parameter cannot be null.

//@flow
function acceptsOptionalString(value?: string) {
 //...
}

acceptsOptionalString("bar");//Works!
acceptsOptionalString(undefined);//Works!
acceptsOptionalString(null);//Error!
acceptsOptionalString();//Works!

Text type

The literal type uses a specific value as the type:

function foo(value: 2) {}

foo(2);//Work!
foo(3);//Error!
foo('2');//Error!

You can use these types of primitive values:

  • Boolean value: true or false
  • Number: like 42 or 3.14
  • String: like "foo" or "bar"
//@flow
function getColor(name: "success" | "warning" | "danger") {
  switch (name) {
    case "success": return "green";
    case "warning": return "yellow";
    case "danger": return "red";
  }
}

getColor("success");//Works!
getColor("danger");//Works!
//$ExpectError
getColor("error");//Error!

Mixed

Sometimes we are not sure what type of value we need. At this time, we can use a mixed type to represent it, but before using the value, we need to determine which type the value is, otherwise it will cause an error:

//@flow
function stringify(value: mixed) {
 //$ExpectError
  return "" + value;//Error!
}

stringify("foo");
//@flow
function stringify(value: mixed) {
  if (typeof value ==='string') {
    return "" + value;//Works!
  } else {
    return "";
  }
}

stringify("foo");

Any type

If you want a way to choose not to use a type checker, any is the way to do it. The use of any is completely unsafe and should be avoided as much as possible.

For example, the following code will not report any errors:

//@flow
function add(one: any, two: any): number {
  return one + two;
}

add(1, 2);//Works.
add("1", "2");//Works.
add({}, []);//Works.

Interface type interface

You can use interface to declare the structure of your desired class.

//@flow
interface Serializable {
  serialize(): string;
}

class Foo {
  serialize() {return'[Foo]';}
}

class Bar {
  serialize() {return'[Bar]';}
}

const foo: Serializable = new Foo();//Works!
const bar: Serializable = new Bar();//Works!

You can also use implements to tell Flow that you want the class to match an interface. This prevents incompatible changes when editing classes.

//@flow
interface Serializable {
  serialize(): string;
}

class Foo implements Serializable {
  serialize() {return'[Foo]';}//Works!
}

class Bar implements Serializable {
 //$ExpectError
  serialize() {return 42;}//Error!
}

Array type Array

To create an array type, you can use Array<Type>type, where Type is the type of elements in the array. For example, create a type for the number array you use Array<number>.

let arr: Array<number> = [1, 2, 3];

For the time being, I will introduce so much, and there are some types of articles that are not mentioned. For more and more detailed content, please check Flow official website .

4. Remove Flow content

Because the syntax of Flow is not standard JavaScript syntax, we need to remove the code related to Flow before the code is finally launched (mainly the description of the fixed type, if you just add @flow, you can apply it directly)

flow-remove-types

This program will remove all your content marked with @flow. . Then place the removed code in the specified directory after generation

npm i -g flow-remove-types
flow-remove-types src/--out-dir dist/
# src Source file address
# dist generated address

babel+webpack

Install a webpack plugin

npm i -D flow-babel-webpack-plugin

We then modify .babelrcthe file, add the following configuration:

{
  "plugins": [
      "transform-flow-comments"
  ]
}

Then add in the webpack.config.jsor webpack.dev.config.js,, webpack.prod.config.jsand files:

const FlowBabelWebpackPlugin = require('flow-babel-webpack-plugin')
module.exports = {
  plugins: [
      new FlowBabelWebpackPlugin()
  ]
}

When babel compiles JavaScript, it also removes Flow content.

Most of the posts on the Internet are of different depths, and even some are inconsistent. The articles below are summaries of the learning process. If you find errors, please leave a message to point out~

Reference: Use Flow to detect your JS vue2.0 project configuration flow type checking to enhance the experience of front-end development with flow.js Flow static type checking and use in Vue project how to use the flow js in the project

Reference: https://cloud.tencent.com/developer/article/1356672 JS static type checking tool Flow-Cloud + Community-Tencent Cloud