Modern JavaScript Web Development Cookbook
上QQ阅读APP看书,第一时间看更新

Basic types in Flow

The possible data types definitions can be found at https://flow.org/en/docs/types/—we won't copy them all here, but rather show you the main ones through a few examples. Please look at the full documentation because there's a great variety of possibilities that you should be aware of:

We will find out how to assign or define types for these definitions in the  Defining types for arrow functions recipe, later in this chapter.

We can see some examples of the definitions in the following code. I disabled ESLint's rule about unused variables to avoid obvious problems:

// Source file: src/types_basic.js

/* @flow */
/* eslint-disable no-unused-vars */

let someFlag: boolean;
let greatTotal: number;
let firstName: string;

function toString(x: number): string {
return String(x);
}

function addTwo(x: number | string, y: number | string) {
return x + y;
}

function showValue(z: mixed): void {
// not returning anything
console.log("Showing... ", z);
}

let numbersList: Array<number>;
numbersList = [22, 9, 60]; // OK
numbersList[1] = "SEP"; // error; cannot assign a string to a number

let anotherList: number[] = [12, 4, 56];

// continues...
The   addTwo()  definition has a hidden problem: are you sure that  x  and   y  will always be of the same type? Actually,   x  could be a number and   y  could be a string, and Flow wouldn't complain. We have no easy way of testing this, and a runtime check for   typeof x === typeof y  would be needed.

When you define an object, you should provide data types for all of its properties and methods. Object definitions are considered to be sealed, meaning that you cannot change the object types. If you cannot or won't do this, start with an empty object, and then Flow will let you add properties at will:

// ...continued

let sealedObject: { name: string, age?: number } = { name: "" };

sealedObject.name = "Ivan Horvat"; // OK

sealedObject.id = 229; // error: key isn't defined in the data type

sealedObject = { age: 57 }; // error: mandatory "name" field is missing

let unsealedObject = {};
unsealedObject.id = 229; // OK
If a function expects an object with some properties, and it receives an object with those properties plus some extra ones, Flow won't complain. If you don't want this, use exact objects; see   https://flow.org/en/docs/types/objects/#toc-exact-object-types. However, this also causes problems, such as disabling the spread operator; see   https://github.com/facebook/flow/issues/2405 for a (two year long!) discussion.

Now, let's turn to more complex definitions, which you will probably end up using, since they better match usual business requirements and program specifications.