Recently, I saw an introduction about Flow in an article. I think it's very good. Although it's easy to use Typescript in a project before, it's a bit cumbersome to use Flow again, but it's always right to learn more.
brief introduction
JS, as a scripting language, has no type checking. This feature is sometimes used very well, but when you are working on a larger project, you will find that this is actually a terrible thing, because programmers who work with you often don't know exactly what type of code you are writing is correct, and it's also troublesome when refactoring code. So based on this requirement, we have the production of Typescript and Flow. Today we mainly introduce Flow.
install
Because the author has been using WebStorm, there is some support for Flow within WebStorm, so if you also use WebStorm, it will be much more convenient.
yarn add --dev flow-bin babel-cli babel-preset-flow
After installing the above package, create the. babelrc file:
{ "presets": ["flow"] }
Setting up WebStorm
With File > Settings > Languages & Frameworks > JavaScript as shown below, Flow package can choose flow-bin under your project, and of course you can install flow-bin globally, then you can use Flow in every project after setting up here.
flow can't be used directly in node or browser environments, so we have to compile with babel before we can use it:
Now that the environment is ready, there is only one last step to initialize this project as a Flow project:
yarn run flow init
Now when we use Flow in a project, WebStorm can give intelligent hints.
Use
type
The latest ECMAScript standard defines seven data types:
-
6 kinds Primitive type:
and Object
These types are also used as annotations in Flow:
Use the original type:
// @flow function method(x: number, y: string, z: boolean) { // ... } method(3.14, "hello", true);
Use object types:
// @flow function method(x: Number, y: String, z: Boolean) { // ... } method(new Number(42), new String("world"), new Boolean(false));
It's important to note that the lowercase number is the original type, while the uppercase Number is the constructor of JavaScript and the object type.
Boolean
In Flow, typing is not converted by default. If you need to convert a type, use either 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 denotes 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
Perhaps types are used for optional values, and you can create them by adding a question mark (such as? string or? number) before the type.
In addition to the question mark, the following type may also be null or void.
// @flow function acceptsMaybeString(value: ?string) { // ... } acceptsMaybeString("bar"); // Works! acceptsMaybeString(undefined); // Works! acceptsMaybeString(null); // Works! acceptsMaybeString(); // Works!
Optional object properties
Object types can have optional attributes, question marks? After attribute names.
{ propertyName?: string }
In addition to their set value types, these optional attributes can also be completely omitted by void. But they can't 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. Again, this parameter cannot be null.
// @flow function acceptsOptionalString(value?: string) { // ... } acceptsOptionalString("bar"); // Works! acceptsOptionalString(undefined); // Works! acceptsOptionalString(null); // Error! acceptsOptionalString(); // Works!
Text type
The text 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 raw values:
- Boer: true or false
- Numbers: 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 type mixed
Sometimes we can't determine what type of value we need. At this point we can use mixed type to express it. But before using the value, we need to determine which type it is, otherwise it will cause errors.
// @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 type checkers, any is the way to do this.
The use of any is completely unsafe and should be avoided as far as possible.
For example, the following code does 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 the class you expect.
// @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 classes 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
To create an array type, you can use the Array < Type > type, where Type is the type of element in the array. For example, create a type Array < number > for the number array you use.
let arr: Array<number> = [1, 2, 3];
So much for the time being. There are some types of articles that are not mentioned. For more details, please Flow official website Check in.