flow类型检查

https://blog.csdn.net/tangxiujiang/article/details/80778627

Flow的简单介绍

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tangxiujiang/article/details/80778627

1、什么是Flow

是 facebook 出品的 JavaScript 静态类型检查工具,https://flow.org/en/docs/usage/这是其官方文档链接

Vue.js 的源码利用了Flow 做了静态类型检查

2、为什么使用Flow

JavaScript 是动态类型语言,它的灵活性有目共睹,但是过于灵活的副作用是很容易就写出非常隐蔽的隐患代码,在编译期甚至看上去都不会报错,但在运行阶段就可能出现各种奇怪的 bug

类型检查的定义:类型检查,就是在编译期尽早发现(由类型错误引起的)bug,又不影响代码运行(不需要运行时动态检查类型),使编写 JavaScript 具有和编写 Java 等强类型语言相近的体验

在vue中使用Flow做静态类型检查,是因为 Babel 和 ESLint 都有对应的 Flow 插件以支持语法,可以完全沿用现有的构建配置,非常小成本的改动就可以拥有静态类型检查的能力

3、Flow的工作方式(类型检查的方式)--两种

类型判断:不需要修改代码,即可进行类型检查,自动通过变量的使用上下文来推断出变量类型,然后根据这些推断来检查类型

类型注释:事先注释好我们期待的类型,Flow 会基于这些注释来判断

一些常见的类型注释的语法:

 1)函数的类型注释

  1.  
    function add(x: number, y: number): number {
  2.  
    return x + y //x的类型是number,y的类型是number,函数的返回值类型是number
  3.  
    }
  4.  
    add('Hello', 11)
 2)数组类型注释:Array<T>,T表示数组中每项的数据类型
  1.  
    var arr: Array<number> = [1, 2, 3]
  2.  
    arr.push('Hello')
3)类类型注释
  1.  
    class Bar {
  2.  
    x: string; // x 是字符串
  3.  
    y: string | number; // y 可以是字符串或者数字
  4.  
    z: boolean;
  5.  
    constructor(x: string, y: string | number) {
  6.  
    this.x = x
  7.  
    this.y = y
  8.  
    this.z = false
  9.  
    }
  10.  
    }
  11.  
    var bar: Bar = new Bar('hello', 4)
4)对象类型注释
  1.  
    var obj: { a: string, b: number, c: Array<string>, d: Bar } = {
  2.  
    a: 'hello',
  3.  
    b: 11,
  4.  
    c: ['hello', 'world'],
  5.  
    d: new Bar('hello', 3)
  6.  
    }
5)如果想指定类型为null或者undefined,只需要写成?T形式
var foo: ?string = null   //foo可以为字符串也可以为bull
4、Flow中的libdef概念

Flow中的libdef可以用来识别第三方库或者是自定义类型

在vue.js的主目录下有.flowconfig文件,它是Flow的配置文件,Vue.js中很多自定义类型都在里面定义,如果遇到某个类型并想了解它完整的数据结构的时候,可以回来翻阅这些数据结构的定义

javascript的类型检查工具有:Flow、TypeScript等

 

下面是对官网的类型注释的翻译

1、Primitive Types---原始类型,Number  Boolean   String   undefined    null    Symbol

  1.  
    1、类型是文字的小写字母开头的
  2.  
    // @flow
  3.  
    function method(x: number, y: string, z: boolean) {
  4.  
    // ...
  5.  
    }
  6.  
    method(3.14, "hello", true);
  7.  
     
  8.  
    2、类型是大写字母开头的
  9.  
    // @flow
  10.  
    function method(x: Number, y: String, z: Boolean) {
  11.  
    // ...
  12.  
    }
  13.  
    method(new Number(42), new String("world"), new Boolean(false));

1)Boolean:在Flow中,参数为boolean类型只有false  true两个值

  1.  
    // @flow
  2.  
    function acceptsBoolean(value: boolean) {
  3.  
    // ...
  4.  
    }
  5.  
    acceptsBoolean(true); // Works!
  6.  
    acceptsBoolean(false); // Works!
  7.  
    acceptsBoolean("foo"); // Error!
  8.  
     
  9.  
    做简单的转换
  10.  
    if (42) {} // 42 => true
  11.  
    if ("") {} // "" => false
  12.  
     
  13.  
     
  14.  
    如果参数是boolean类型,使用的时候参数为数值类型需要转换成非Boolean类型,Boolean(x) 或者 !!x
  15.  
    // @flow
  16.  
    function acceptsBoolean(value: boolean) {
  17.  
    // ...
  18.  
    }
  19.  
    acceptsBoolean(0); // Error!
  20.  
    acceptsBoolean(Boolean(0)); // Works!
  21.  
    acceptsBoolean(!!0); // Works!
2)Number:在js中认为NaN   Infinity也是数字
  1.  
    // @flow
  2.  
    function acceptsNumber(value: number) {
  3.  
    // ...
  4.  
    }
  5.  
    acceptsNumber(42); // Works!
  6.  
    acceptsNumber(3.14); // Works!
  7.  
    acceptsNumber(NaN); // Works!
  8.  
    acceptsNumber(Infinity); // Works!
  9.  
    acceptsNumber("foo"); // Error!
3)String:在Flow中变量声明为string类型只接受string类型;两个变量相加的时候,只接受string和number的拼接,其他类型需要显示的转化为string类型
  1.  
    // @flow
  2.  
    function acceptsString(value: string) {
  3.  
    // ...
  4.  
    }
  5.  
    acceptsString("foo"); // Works! 只接受字符串类型
  6.  
    acceptsString(false); // Error!
  7.  
     
  8.  
    // @flow 两个变量相加的时候,只接受string和number的拼接
  9.  
    "foo" + "foo"; // Works!
  10.  
    "foo" + 42; // Works!
  11.  
    "foo" + {}; // Error!
  12.  
    "foo" + []; // Error!
  13.  
     
  14.  
    // @flow 其他类型需要显示的转化为String类型
  15.  
    "foo" + String({}); // Works!
  16.  
    "foo" + [].toString(); // Works!
  17.  
    "" + JSON.stringify({}) // Works!
4)null  和void(undefined):在js中的类型是null和undefined,但是在Flow中是null和void
  1.  
    // @flow
  2.  
    function acceptsNull(value: null) {
  3.  
    /* ... */
  4.  
    }
  5.  
    function acceptsUndefined(value: void) {
  6.  
    /* ... */
  7.  
    }
  8.  
    acceptsNull(null); // Works!
  9.  
    acceptsNull(undefined); // Error!
  10.  
    acceptsUndefined(null); // Error!
  11.  
    acceptsUndefined(undefined); // Works!
2、Literal  Types---文字值类型

  1.  
    // @flow
  2.  
    function acceptsTwo(value: 2) { //文字值类型声明参数的值
  3.  
    // ...
  4.  
    }
  5.  
    acceptsTwo(2); // Works!
  6.  
    // $ExpectError
  7.  
    acceptsTwo(3); // Error!
  8.  
    // $ExpectError
  9.  
    acceptsTwo("2"); // Error!
3、Mixed  Types---混合类型
参数类型是单一类型
  1.  
    function square(n: number) {
  2.  
    return n * n;
  3.  
    }
参数类型是不同类型,使用|来声明
  1.  
    function stringifyBasicValue(value: string | number) {
  2.  
    return '' + value;
  3.  
    }
一种类型依赖于另一种类型,函数的返回值类型依赖于参数值的类型
  1.  
    function identity<T>(value: T): T {
  2.  
    return value;
  3.  
    }
使用mixed声明参数的类型,即参数的类型是未知的
  1.  
    function getTypeOf(value: mixed): string {
  2.  
    return typeof value;
  3.  
    }
mixed类型可以是任意类型,但是在使用该类型的参数进行运算的时候,需要判断他的具体类型,否则则会报错
  1.  
    // @flow mixed类型的参数可以是任意类型
  2.  
    function stringify(value: mixed) {
  3.  
    // ...
  4.  
    }
  5.  
    stringify("foo");
  6.  
    stringify(3.14);
  7.  
    stringify(null);
  8.  
    stringify({});
  9.  
     
  10.  
    // @flow 在使用mixed类型的参数进行运算的时候,需要判断他的类型
  11.  
    function stringify(value: mixed) {
  12.  
    // $ExpectError
  13.  
    return "" + value; // Error!
  14.  
    }
  15.  
    stringify("foo");
  16.  
     
  17.  
    // @flow
  18.  
    function stringify(value: mixed) {
  19.  
    if (typeof value === 'string') {
  20.  
    return "" + value; // Works!
  21.  
    } else {
  22.  
    return "";
  23.  
    }
  24.  
    }
  25.  
    stringify("foo");
4、Any Types---任意类型(谨慎使用)
  1.  
    // @flow 不会去判断类型,任意类型都可以在一起运算
  2.  
    function add(one: any, two: any): number {
  3.  
    return one + two;
  4.  
    }
  5.  
    add(1, 2); // Works.
  6.  
    add("1", "2"); // Works.
  7.  
    add({}, []); // Works.

5、Maybe  Types---可能的类型,使用?标记

  1.  
    // @flow 比如?number---表示参数类型可以是number null undefined
  2.  
    function acceptsMaybeNumber(value: ?number) {
  3.  
    // ...
  4.  
    }
  5.  
    acceptsMaybeNumber(42); // Works!
  6.  
    acceptsMaybeNumber(); // Works!
  7.  
    acceptsMaybeNumber(undefined); // Works!
  8.  
    acceptsMaybeNumber(null); // Works!
  9.  
    acceptsMaybeNumber("42"); // Error!
  1.  
    // @flow 如果在Maybe Types中想使用的是number类型,那么需要先判断其为number类型,然后再进行处理
  2.  
    function acceptsMaybeNumber(value: ?number) {
  3.  
    if (value !== null && value !== undefined) { //比较复杂的判断
  4.  
    return value * 2;
  5.  
    }
  6.  
    }
  7.  
     
  8.  
    // @flow
  9.  
    function acceptsMaybeNumber(value: ?number) {
  10.  
    if (value != null) { // 使用 != 来比较
  11.  
    return value * 2;
  12.  
    }
  13.  
    }
  14.  
    // @flow
  15.  
    function acceptsMaybeNumber(value: ?number) {
  16.  
    if (typeof value === 'number') { // 使用===来判断
  17.  
    return value * 2;
  18.  
    }
  19.  
    }
6、Variable  Types---变量类型

js中有3种方法声明变量,分别是var   let  const

var---声明的变量有提升的作用,可以重新赋值

let---声明块级作用域的变量,可以重新赋值

const---声明块级作用域的变量,声明的时候要初始化,不可以重新赋值

  1.  
    // @flow
  2.  
    const foo /* : number */ = 1;
  3.  
    const bar: number = 2;
  1.  
    // @flow 当在声明一个变量的时候提供类型注释,那么在重新赋值的时候,也只能赋予 相同类型的值
  2.  
    let foo: number = 1;
  3.  
    foo = 2; // Works!
  4.  
    // $ExpectError
  5.  
    foo = "3"; // Error!
  1.  
    //当在声明一个类型的时候,没有使用类型注释,那么在改变变量的类型的时候,在声明另一个类型的时候,需要给这个类型提供所有的类型注释
  2.  
    let foo = 42;
  3.  
    if (Math.random()) foo = true;
  4.  
    if (Math.random()) foo = "hello";
  5.  
    let isOneOf: number | boolean | string = foo; // Works!
  1.  
    // @flow 在if语句、函数和其他条件代码块里面,Flow不能判断变量改变之后的类型
  2.  
    let foo = 42;
  3.  
    function mutate() {
  4.  
    foo = true;
  5.  
    foo = "hello";
  6.  
    }
  7.  
    mutate();
  8.  
    // $ExpectError
  9.  
    let isString: string = foo; // Error!
7、Function   Types---函数类型 ,在参数和返回值的类型注释
  1.  
    // @flow
  2.  
    function concat(a: string, b: string): string {
  3.  
    return a + b;
  4.  
    }
  5.  
    concat("foo", "bar"); // Works!
  6.  
    // $ExpectError
  7.  
    concat(true, false); // Error!

设置可选参数:param?:type   ,参数可以没有设置、undefined、match type,但不能为null

  1.  
    // @flow
  2.  
    function method(optionalValue?: string) {
  3.  
    // ...
  4.  
    }
  5.  
    method(); // Works.
  6.  
    method(undefined); // Works.
  7.  
    method("string"); // Works.
  8.  
    // $ExpectError
  9.  
    method(null); // Error!

 

在Flow中有3种类型的函数类型声明

1)函数声明

  1.  
    function method(str, bool, ...nums) {
  2.  
    // ...
  3.  
    }
  4.  
     
  5.  
    function method(str: string, bool?: boolean, ...nums: Array<number>): void {
  6.  
    // ...
  7.  
    }
2)箭头函数
  1.  
    let method = (str, bool, ...nums) => {
  2.  
    // ...
  3.  
    };
  4.  
     
  5.  
    let method = (str: string, bool?: boolean, ...nums: Array<number>): void => {
  6.  
    // ...
  7.  
    };
3)函数类型
  1.  
    (str: string, bool?: boolean, ...nums: Array<number>) => void
  2.  
     
  3.  
    //可以省略参数名
  4.  
    (string, boolean | void, Array<number>) => void
  5.  
    //设置回调函数
  6.  
    function method(callback: (error: Error | null, value: string | null) => void) {
  7.  
    // ...
  8.  
    }
  9.  
     
  10.  
     
  11.  
    (str: string, bool?: boolean, ...nums: Array<number>) => void
  12.  
     
  13.  
    //可以省略参数名
  14.  
    (string, boolean | void, Array<number>) => void
  15.  
    //设置回调函数
  16.  
    function method(callback: (error: Error | null, value: string | null) => void) {
  17.  
    // ...
  18.  
    }

rest参数:  ...   必须为数组,且放在参数的最后面

  1.  
    // @flow
  2.  
    function method(...args: Array<number>) {
  3.  
    // ...
  4.  
    }
  5.  
     
  6.  
    method(); // Works.
  7.  
    method(1); // Works.
  8.  
    method(1, 2); // Works.
  9.  
    method(1, 2, 3); // Works.
函数返回值:  通过  :type  设置   注意设置了返回值类型,就一定要return该类型,否则报错
  1.  
    // @flow
  2.  
    // $ExpectError
  3.  
    function method(): boolean {
  4.  
    if (Math.random() > 0.5) { //对于不符合if语句的话,函数会返回undefined,和boolean类型不匹配,所以报错
  5.  
    return true;
  6.  
    }
  7.  
    }

函数中的this:在Flow中胡会自动识别this的上下文环境

  1.  
    function method() {
  2.  
    return this;
  3.  
    }
  4.  
    var num: number = method.call(42);
  5.  
    // $ExpectError
  6.  
    var str: string = method.call(42);

谓词函数:%check

  1.  
    //报错
  2.  
    function truthy(a, b): boolean {
  3.  
    return a && b;
  4.  
    }
  5.  
     
  6.  
    function concat(a: ?string, b: ?string): string {
  7.  
    if (truthy(a, b)) {
  8.  
    // $ExpectError
  9.  
    return a + b;
  10.  
    }
  11.  
    return '';
  12.  
    }
  13.  
     
  14.  
    //修正
  15.  
    function truthy(a, b): boolean %checks {
  16.  
    return !!a && !!b;
  17.  
    }
  18.  
     
  19.  
    function concat(a: ?string, b: ?string): string {
  20.  
    if (truthy(a, b)) {
  21.  
    return a + b;
  22.  
    }
  23.  
    return '';
  24.  
    }
  1.  
    function isString(y): %checks {
  2.  
    return typeof y === "string";
  3.  
    }
  4.  
     
  5.  
    function isNumber(y): %checks {
  6.  
    return typeof y === "number";
  7.  
    }
  8.  
     
  9.  
    function isNumberOrString(y): %checks {
  10.  
    return isString(y) || isNumber(y);
  11.  
    }
  12.  
     
  13.  
    function foo(x): string | number {
  14.  
    if (isNumberOrString(x)) {
  15.  
    return x + x;
  16.  
    } else {
  17.  
    return x.length; // no error, because Flow infers that x can only be an array
  18.  
    }
  19.  
    }
  20.  
     
  21.  
    foo('a');
  22.  
    foo(5);
  23.  
    foo([]);
8、Object   Types---对象类型
  1.  
    // @flow
  2.  
    var obj1: { foo: boolean } = { foo: true };
  3.  
    var obj2: {
  4.  
    foo: number,
  5.  
    bar: boolean,
  6.  
    baz: string,
  7.  
    } = {
  8.  
    foo: 1,
  9.  
    bar: true,
  10.  
    baz: 'three',
  11.  
    };

 在js中访问对象不存在的属性会得到undefined,而在Flow里面访问对象不存在的属性,会报错

  1.  
    // @flow 在js中访问对象不存在的属性会得到undefined,而在Flow里面访问对象不存在的属性,会报错
  2.  
    var obj = { foo: "bar" };
  3.  
    // $ExpectError
  4.  
    obj.bar; // Error!
可以通过设置   属性名?:type   来设置属性为void / omitted /  match type  但不能为null
  1.  
    // @flow 可以通过设置 属性名?:type 来设置属性为void / omitted / match type 但不能为null
  2.  
    var obj: { foo?: boolean } = {};
  3.  
    obj.foo = true; // Works!
  4.  
    // $ExpectError
  5.  
    obj.foo = 'hello'; // Error!
  6.  
     
  7.  
    // @flow
  8.  
    function acceptsObject(value: { foo?: string }) {
  9.  
    // ...
  10.  
    }
  11.  
    acceptsObject({ foo: "bar" }); // Works!
  12.  
    acceptsObject({ foo: undefined }); // Works!
  13.  
    // $ExpectError
  14.  
    acceptsObject({ foo: null }); // Error!
  15.  
    acceptsObject({}); // Works!
当在Flow中声明一个对象的属性的值的时候,Flow会直到属性的类型,对象的属性值只能赋给同类型的变量,同时在这种情况下不能另外声明属性
  1.  
    // @flow 在声明一个对象的属性的时候赋予属性值,那么其属性只能赋给相同类型的变量
  2.  
    var obj = {
  3.  
    foo: 1,
  4.  
    bar: true,
  5.  
    baz: 'three'
  6.  
    };
  7.  
     
  8.  
    var foo: number = obj.foo; // Works!
  9.  
    var bar: boolean = obj.bar; // Works!
  10.  
    // $ExpectError
  11.  
    var baz: null = obj.baz; // Error!
  12.  
    var bat: string = obj.bat; // Error!
  13.  
    // $ExpectError 在这种况下不能再声明其他属性
  14.  
    obj.bass = true; // Error!
  15.  
    // $ExpectError
  16.  
    obj.bahhh = 'three'; // Error!
声明变量的时候没有赋予对象任何属性,此时可以添加额外的属性
  1.  
    // @flow
  2.  
    var obj = {};
  3.  
     
  4.  
    obj.foo = 1; // Works!
  5.  
    obj.bar = true; // Works!
  6.  
    obj.baz = 'three'; // Works!
给unsealed object重新赋值的时候,将其属性值赋予给另一个变量,此时该变量要列出所有该对象的属性type
  1.  
    // @flow
  2.  
    var obj = {};
  3.  
     
  4.  
    if (Math.random()) obj.prop = true;
  5.  
    else obj.prop = "hello";
  6.  
     
  7.  
    // $ExpectError
  8.  
    var val1: boolean = obj.prop; // Error!
  9.  
    // $ExpectError
  10.  
    var val2: string = obj.prop; // Error!
  11.  
    var val3: boolean | string = obj.prop; // Works!
能推断对象属性的类型
  1.  
    var obj = {};
  2.  
     
  3.  
    obj.foo = 1;
  4.  
    obj.bar = true;
  5.  
     
  6.  
    var foo: number = obj.foo; // Works!
  7.  
    var bar: boolean = obj.bar; // Works!
  8.  
    var baz: string = obj.baz; // Works?
宽子类型
  1.  
    // @flow
  2.  
    function method(obj: { foo: string }) {
  3.  
    // ...
  4.  
    }
  5.  
     
  6.  
    method({
  7.  
    foo: "test", // Works!
  8.  
    bar: 42 // Works!
  9.  
    });
索引属性
  1.  
    // @flow
  2.  
    var o: { [string]: number } = {};
  3.  
    o["foo"] = 0;
  4.  
    o["bar"] = 1;
  5.  
    var foo: number = o["foo"];
  1.  
    // @flow
  2.  
    var obj: { [user_id: number]: string } = {};
  3.  
    obj[1] = "Julia";
  4.  
    obj[2] = "Camille";
  5.  
    obj[3] = "Justin";
  6.  
    obj[4] = "Mark";
9、Array  Types---数组类型

在js中的Array的定义如下所示:

  1.  
    new Array(1, 2, 3); // [1, 2, 3];
  2.  
    new Array(3); // [undefined, undefined, undefined]
  3.  
    [1, 2, 3]; // [1, 2, 3];
  4.  
    let arr = []; // []
  5.  
    arr[0] = 1; // [1]
  6.  
    arr[1] = 2; // [1, 2]
  7.  
    arr[2] = 3; // [1, 2, 3]
使用  param: Array<type>来声明数组类型,其中type是数组元素的类型  
  1.  
    let arr1: Array<boolean> = [true, false, true];
  2.  
    let arr2: Array<string> = ["A", "B", "C"];
  3.  
    let arr3: Array<mixed> = [1, true, "three"]
  4.  
    let arr: Array<number> = [1, 2, 3];
使用精简的写法:type[]
let arr: number[] = [0, 1, 2, 3];
?type[]   = ? Array<type>:表示元素成员可以match type,或者整个为null
  1.  
    // @flow
  2.  
    let arr1: ?number[] = null; // Works!
  3.  
    let arr2: ?number[] = [1, 2]; // Works!
  4.  
    let arr3: ?number[] = [null]; // Error!
Array<?type> = (?type)[]:表示成员可以为null、match type
  1.  
    // @flow
  2.  
    let arr1: (?number)[] = null; // Error!
  3.  
    let arr2: (?number)[] = [1, 2]; // Works!
  4.  
    let arr3: (?number)[] = [null]; // Works!
当访问数组的元素超过数组的索引,那么在Flow中会标记其值为undefined
  1.  
    // @flow
  2.  
    let array: Array<number> = [0, 1, 2];
  3.  
    let value: number = array[3]; // Works.
  4.  
    // ^ undefined
  5.  
     
  6.  
    // @flow
  7.  
    let array: Array<number> = [];
  8.  
    array[0] = 0;
  9.  
    array[2] = 2;
  10.  
    let value: number = array[1]; // Works.
  11.  
    // ^ undefined
  12.  
     
  13.  
    // @flow
  14.  
    let array: Array<number> = [0, 1, 2];
  15.  
    let value: number | void = array[1];
  16.  
    if (value !== undefined) {
  17.  
    // number
  18.  
    }
9、Tuple  Types---元祖类型  [type,type,type]  元祖使用数组声明
  1.  
    let tuple1: [number] = [1];
  2.  
    let tuple2: [number, boolean] = [1, true];
  3.  
    let tuple3: [number, boolean, string] = [1, true, "three"];
从元祖中通过索引去获取元祖元素的时候,在Flow中会返回该元素类型的值
  1.  
    // @flow
  2.  
    let tuple: [number, boolean, string] = [1, true, "three"];
  3.  
    let num : number = tuple[0]; // Works!
  4.  
    let bool : boolean = tuple[1]; // Works!
  5.  
    let str : string = tuple[2]; // Works!
如果访问一个超出索引的元祖的元素的时候,Flow会返回一个void值
  1.  
    // @flow
  2.  
    let tuple: [number, boolean, string] = [1, true, "three"];
  3.  
    let none: void = tuple[3];
如果不确定返回元祖的那个索引的值,那么在用元祖的元素去赋值给的另一个变量的时候要列出元祖的所有类型
  1.  
    // @flow
  2.  
    let tuple: [number, boolean, string] = [1, true, "three"];
  3.  
    function getItem(n: number) {
  4.  
    let val: number | boolean | string = tuple[n];
  5.  
    // ...
  6.  
    }
当给元祖的元素重新赋值的时候,赋予的值类型要和原来的类型一致
  1.  
    // @flow
  2.  
    let tuple: [number, boolean, string] = [1, true, "three"];
  3.  
    tuple[0] = 2; // Works!
  4.  
    tuple[1] = false; // Works!
  5.  
    tuple[2] = "foo"; // Works!
  6.  
     
  7.  
    // $ExpectError
  8.  
    tuple[0] = "bar"; // Error!
  9.  
    // $ExpectError
  10.  
    tuple[1] = 42; // Error!
  11.  
    // $ExpectError
  12.  
    tuple[2] = false; // Error!
元祖的长度称为元数,短的元祖不能赋值给长的元数,长的元祖不能赋值给短的元数,即只有元数相同的时候才能赋值
  1.  
    // @flow
  2.  
    let tuple1: [number, boolean] = [1, true];
  3.  
    // $ExpectError
  4.  
    let tuple2: [number, boolean, void] = tuple1; // Error!
  5.  
     
  6.  
    // @flow
  7.  
    let tuple1: [number, boolean, void] = [1, true];
  8.  
    // $ExpectError
  9.  
    let tuple2: [number, boolean] = tuple1; // Error!
数组和元祖不能相互赋值
  1.  
    // @flow
  2.  
    let array: Array<number> = [1, 2];
  3.  
    // $ExpectError
  4.  
    let tuple: [number, number] = array; // Error!
  5.  
     
  6.  
    // @flow
  7.  
    let tuple: [number, number] = [1, 2];
  8.  
    // $ExpectError
  9.  
    let array: Array<number> = tuple; // Error!
不能使用Array.prototype上的方法操作元祖 
  1.  
    // @flow
  2.  
    let tuple: [number, number] = [1, 2];
  3.  
    tuple.join(', '); // Works!
  4.  
    // $ExpectError
  5.  
    tuple.push(3); // Error!
10、Class  Types---类类型 
  1.  
    //使用自定义类声明一个变量
  2.  
    class MyClass {
  3.  
    // ...
  4.  
    }
  5.  
    let myInstance: MyClass = new MyClass();
  6.  
     
  7.  
    //类函数
  8.  
    class MyClass {
  9.  
    method(value: string): number { /* ... */ }
  10.  
    }
在Flow中使用公有属性的时候,必须先声明他的类型
  1.  
    // @flow 错误
  2.  
    class MyClass {
  3.  
    method() {
  4.  
    // $ExpectError
  5.  
    this.prop = 42; // Error!
  6.  
    }
  7.  
    }
  8.  
     
  9.  
    // @flow 正确
  10.  
    class MyClass {
  11.  
    prop: number;
  12.  
    method() {
  13.  
    this.prop = 42;
  14.  
    }
  15.  
    }
直接声明属性:下面两种写法都是正确的
  1.  
    class MyClass {
  2.  
    prop = 42;
  3.  
    }
  4.  
    class MyClass {
  5.  
    prop: number = 42;
  6.  
    }
类泛型:给类的属性指定里面一共有哪些数据类型,在赋值的时候才给出明确的类型
  1.  
    // @flow
  2.  
    class MyClass<A, B, C> {
  3.  
    constructor(arg1: A, arg2: B, arg3: C) {
  4.  
    // ...
  5.  
    }
  6.  
    }
  7.  
    var val: MyClass<number, boolean, string> = new MyClass(1, true, 'three');
11、Type  Aliase---类型别名  使用type param  =  type 来声明,声明的类型别名可以用在任何地方
  1.  
    // @flow
  2.  
    type MyObject = {
  3.  
    foo: number,
  4.  
    bar: boolean,
  5.  
    baz: string,
  6.  
    };
  7.  
     
  8.  
    var val: MyObject = { /* ... */ };
  9.  
    function method(val: MyObject) { /* ... */ }
  10.  
    class Foo { constructor(val: MyObject) { /* ... */ } }
  1.  
     
  2.  
    type NumberAlias = number;
  3.  
    type ObjectAlias = {
  4.  
    property: string,
  5.  
    method(): number,
  6.  
    };
  7.  
    type UnionAlias = 1 | 2 | 3;
  8.  
    type AliasAlias = ObjectAlias;
类型别名泛型
  1.  
    // @flow
  2.  
    type MyObject<A, B, C> = {
  3.  
    foo: A,
  4.  
    bar: B,
  5.  
    baz: C,
  6.  
    };
  7.  
     
  8.  
    var val: MyObject<number, boolean, string> = {
  9.  
    foo: 1,
  10.  
    bar: true,
  11.  
    baz: 'three',
  12.  
    };
12、Opaque  Type  Aliase--- 不透明类型别名
13、Interface  Type  --- 接口类型
在Flow中,不同的类中有同名属性和函数名是不允许的
  1.  
    // @flow
  2.  
    class Foo {
  3.  
    serialize() { return '[Foo]'; }
  4.  
    }
  5.  
    class Bar {
  6.  
    serialize() { return '[Bar]'; }
  7.  
    }
  8.  
    // $ExpectError
  9.  
    const foo: Foo = new Bar(); // Error!
可以使用interface来声明一个接口
  1.  
    // @flow
  2.  
    interface Serializable {
  3.  
    serialize(): string;
  4.  
    }
  5.  
     
  6.  
    class Foo {
  7.  
    serialize() { return '[Foo]'; }
  8.  
    }
  9.  
     
  10.  
    class Bar {
  11.  
    serialize() { return '[Bar]'; }
  12.  
    }
  13.  
     
  14.  
    const foo: Serializable = new Foo(); // Works!
  15.  
    const bar: Serializable = new Bar(); // Works!

使用implements去匹配接口,可以使用多个接口

 

  1.  
    class Foo implements Bar, Baz {
  2.  
    // ...
  3.  
    }
  1.  
    // @flow
  2.  
    interface Serializable {
  3.  
    serialize(): string;
  4.  
    }
  5.  
     
  6.  
    class Foo implements Serializable {
  7.  
    serialize() { return '[Foo]'; } // Works!
  8.  
    }
  9.  
     
  10.  
    class Bar implements Serializable {
  11.  
    // $ExpectError
  12.  
    serialize() { return 42; } // Error!
  13.  
    }
  1.  
    //接口函数
  2.  
    interface MyInterface {
  3.  
    method(value: string): number;
  4.  
    }
  5.  
     
  6.  
    //接口属性
  7.  
    interface MyInterface {
  8.  
    property: string;
  9.  
    }
  10.  
    interface MyInterface {
  11.  
    property?: string;
  12.  
    }
  13.  
     
  14.  
    //接口映射
  15.  
    interface MyInterface {
  16.  
    [key: string]: number;
  17.  
    }
  18.  
     
  19.  
    接口泛型
  20.  
    / @flow
  21.  
    interface MyInterface<A, B, C> {
  22.  
    foo: A;
  23.  
    bar: B;
  24.  
    baz: C;
  25.  
    }
  26.  
     
  27.  
    var val: MyInterface<number, boolean, string> = {
  28.  
    foo: 1,
  29.  
    bar: true,
  30.  
    baz: 'three',
  31.  
    };
  32.  
     
  33.  
     
  34.  
    //接口属性:只读(+) 只写(-)
  35.  
    // @flow 只读+
  36.  
    interface Invariant { property: number | string }
  37.  
    interface Covariant { +readOnly: number | string }
  38.  
     
  39.  
    function method1(value: Invariant) {
  40.  
    value.property; // Works!
  41.  
    value.property = 3.14; // Works!
  42.  
    }
  43.  
     
  44.  
    function method2(value: Covariant) {
  45.  
    value.readOnly; // Works!
  46.  
    // $ExpectError
  47.  
    value.readOnly = 3.14; // Error!
  48.  
    }
  49.  
     
  50.  
    //只写 -
  51.  
    interface Invariant { property: number }
  52.  
    interface Contravariant { -writeOnly: number }
  53.  
     
  54.  
    function method1(value: Invariant) {
  55.  
    value.property; // Works!
  56.  
    value.property = 3.14; // Works!
  57.  
    }
  58.  
     
  59.  
    function method2(value: Contravariant) {
  60.  
    // $ExpectError
  61.  
    value.writeOnly; // Error!
  62.  
    value.writeOnly = 3.14; // Works!
}14、Generic  Type  --- 泛型类型

  1.  
    // @flow
  2.  
    type IdentityWrapper = {
  3.  
    func<T>(T): T
  4.  
    }
  5.  
     
  6.  
    function identity(value) {
  7.  
    return value;
  8.  
    }
  9.  
     
  10.  
    function genericIdentity<T>(value: T): T {
  11.  
    return value;
  12.  
    }
  13.  
     
  14.  
    // $ExpectError
  15.  
    const bad: IdentityWrapper = { func: identity }; // Error!
  16.  
    const good: IdentityWrapper = { func: genericIdentity }; // Works!
函数泛型
  1.  
    //1
  2.  
    function method<T>(param: T): T {
  3.  
    // ...
  4.  
    }
  5.  
     
  6.  
    //2
  7.  
    function<T>(param: T): T {
  8.  
    // ...
  9.  
    }
  10.  
     
  11.  
    //3
  12.  
    <T>(param: T) => T
  13.  
     
  14.  
    //4
  15.  
    function method(func: <T>(param: T) => T) {
  16.  
    // ...
  17.  
    }
类泛型
  1.  
    class Item<T> {
  2.  
    prop: T;
  3.  
     
  4.  
    constructor(param: T) {
  5.  
    this.prop = param;
  6.  
    }
  7.  
     
  8.  
    method(): T {
  9.  
    return this.prop;
  10.  
    }
  11.  
    }
类型别名泛型
  1.  
    type Item<T> = {
  2.  
    foo: T,
  3.  
    bar: T,
  4.  
    };
接口泛型
  1.  
    interface Item<T> {
  2.  
    foo: T,
  3.  
    bar: T,
  4.  
    }
15、Union   Type  --- 并集类型  type1  |  type2  |  type3  
  1.  
    // @flow
  2.  
    function toStringPrimitives(value: number | boolean | string) {
  3.  
    return String(value);
  4.  
    }
  5.  
     
  6.  
    toStringPrimitives(1); // Works!
  7.  
    toStringPrimitives(true); // Works!
  8.  
    toStringPrimitives('three'); // Works!
  9.  
     
  10.  
    // $ExpectError
  11.  
    toStringPrimitives({ prop: 'val' }); // Error!
  12.  
    // $ExpectError
  13.  
    toStringPrimitives([1, 2, 3, 4, 5]); // Error!
多行声明
  1.  
    type Foo =
  2.  
    | Type1
  3.  
    | Type2
  4.  
    | ...
  5.  
    | TypeN
声明多种类型

  1.  
    type Numbers = 1 | 2;
  2.  
    type Colors = 'red' | 'blue'
  3.  
    type Fish = Numbers | Colors;
在函数中使用并集的时候,需要对所有类型进行处理,否则Flow会报错
  1.  
    // @flow
  2.  
    // $ExpectError 没有对参数是string类型的进行处理,所以Flow报错
  3.  
    function toStringPrimitives(value: number | boolean | string): string { // Error!
  4.  
    if (typeof value === 'number') {
  5.  
    return String(value);
  6.  
    } else if (typeof value === 'boolean') {
  7.  
    return String(value);
  8.  
    }
  9.  
    }
15、Intersection  Type  --- 交集类型    type1 & type2 & type3       参数里面必须书写所有的变量类型
  1.  
    // @flow
  2.  
    type A = { a: number };
  3.  
    type B = { b: boolean };
  4.  
    type C = { c: string };
  5.  
     
  6.  
    function method(value: A & B & C) {
  7.  
    // ...
  8.  
    }
  9.  
     
  10.  
    // $ExpectError
  11.  
    method({ a: 1 }); // Error!
  12.  
    // $ExpectError
  13.  
    method({ a: 1, b: true }); // Error!
  14.  
    method({ a: 1, b: true, c: 'three' }); // Works!
在多行声明
  1.  
    type Foo =
  2.  
    & Type1
  3.  
    & Type2
  4.  
    & ...
  5.  
    & TypeN
  1.  
    type Foo = Type1 & Type2;
  2.  
    type Bar = Type3 & Type4;
  3.  
    type Baz = Foo & Bar;
  1.  
    // @flow
  2.  
    type A = { a: number };
  3.  
    type B = { b: boolean };
  4.  
    type C = { c: string };
  5.  
     
  6.  
    function method(value: A & B & C) {
  7.  
    var a: A = value;
  8.  
    var b: B = value;
  9.  
    var c: C = value;
  10.  
    }
16、typeof  Type  --- 类型检测  typeof  返回一个给定值的类型
  1.  
    // @flow
  2.  
    let num1 = 42;
  3.  
    let num2: typeof num1 = 3.14; // Works!
  4.  
    // $ExpectError
  5.  
    let num3: typeof num1 = 'world'; // Error!
  6.  
     
  7.  
    let bool1 = true;
  8.  
    let bool2: typeof bool1 = false; // Works!
  9.  
    // $ExpectError
  10.  
    let bool3: typeof bool1 = 42; // Error!
  11.  
     
  12.  
    let str1 = 'hello';
  13.  
    let str2: typeof str1 = 'world'; // Works!
  14.  
    // $ExpectError
  15.  
    let str3: typeof str1 = false; // Error!

如果是文字类型的话,就会报错

  1.  
    // @flow
  2.  
    let num1: 42 = 42;
  3.  
    // $ExpectError
  4.  
    let num2: typeof num1 = 3.14; // Error!
  5.  
     
  6.  
    let bool1: true = true;
  7.  
    // $ExpectError
  8.  
    let bool2: typeof bool1 = false; // Error!
  9.  
     
  10.  
    let str1: 'hello' = 'hello';
  11.  
    // $ExpectError
  12.  
    let str2: typeof str1 = 'world'; // Error!
  1.  
    // @flow
  2.  
    let obj1 = { foo: 1, bar: true, baz: 'three' };
  3.  
    let obj2: typeof obj1 = { foo: 42, bar: false, baz: 'hello' };
  4.  
     
  5.  
    let arr1 = [1, 2, 3];
  6.  
    let arr2: typeof arr1 = [3, 2, 1];
17、Type  Casting  Expressions  --- 类型透射表达式   (value : type)
18、Utility  Type
19、Module   Types
20、Common  Types
  1.  
    // @flow
  2.  
     
  3.  
    /*::
  4.  
    type MyAlias = {
  5.  
    foo: number,
  6.  
    bar: boolean,
  7.  
    baz: string,
  8.  
    };
  9.  
    */
  10.  
     
  11.  
    function method(value /*: MyAlias */) /*: boolean */ {
  12.  
    return value.bar;
  13.  
    }
  14.  
     
  15.  
    method({ foo: 1, bar: true, baz: ["oops"] }); //error 类型不匹配
  16.  

posted @ 2018-09-26 15:40  小小公举  阅读(411)  评论(0编辑  收藏  举报