flow中文文档(五)

2018-08-15  本文已影响0人  hhooke

数组类型

要创建数组类型,可以使用Array <Type> type,其中Type是数组中元素的类型。例如,要为数组数组创建类型,请使用Array <number>。

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

You can put any type within Array<Type>.

let arr1: Array<boolean> = [true, false, true];
let arr2: Array<string> = ["A", "B", "C"];
let arr3: Array<mixed> = [1, true, "three"]

快速语法

let arr: number[] = [0, 1, 2, 3];

请注意,?Type []相当于?Array <T>而不是Array <?T>。

// @flow
let arr1: ?number[] = null;   // Works!
let arr2: ?number[] = [1, 2]; // Works!
let arr3: ?number[] = [null]; // Error!

如果你想使它成为Array <?T>你可以使用括号,如:(?Type)[]

// @flow
let arr1: (?number)[] = null;   // Error!
let arr2: (?number)[] = [1, 2]; // Works!
let arr3: (?number)[] = [null]; // Works!

数组访问不安全

从数组中检索元素时,始终存在未定义的元素。您可以访问一个超出数组边界的索引,或者该元素不能存在,因为它是一个“稀疏数组”。

例如,您可能正在访问超出数组范围的元素

// @flow
let array: Array<number> = [0, 1, 2];
let value: number = array[3]; // Works.
                       // ^ undefined

或者你可以访问一个不存在的元素,如果它是一个“稀疏数组”。

// @flow
let array: Array<number> = [];

array[0] = 0;
array[2] = 2;

let value: number = array[1]; // Works.
                       // ^ undefined

为了使这个安全,Flow必须将每个单独的数组访问标记为“可能未定义”。

Flow不会这样做,因为它使用起来非常不方便。您将被迫优化访问数组时获得的每个值的类型。

let array: Array<number> = [0, 1, 2];
let value: number | void = array[1];

if (value !== undefined) {
  // number
}

由于Flow变得更加智能,将来有可能解决这个问题,但是现在你应该意识到这一点。

元组类型

元组是一种列表,但具有有限的项目集。在JavaScript中,使用数组创建元组。

在Flow中,您可以使用[type,type,type]语法创建元组。

let tuple1: [number] = [1];
let tuple2: [number, boolean] = [1, true];
let tuple3: [number, boolean, string] = [1, true, "three"];

当您从特定索引处的元组获取值时,它将返回该索引处的类型。

// @flow
let tuple: [number, boolean, string] = [1, true, "three"];

let num  : number  = tuple[0]; // Works!
let bool : boolean = tuple[1]; // Works!
let str  : string  = tuple[2]; // Works!

如果您尝试从不存在的索引获取它将返回一种void。

// @flow
let tuple: [number, boolean, string] = [1, true, "three"];

let none: void = tuple[3];

如果Flow不知道您尝试访问哪个索引,它将返回所有可能的类型。

// @flow
let tuple: [number, boolean, string] = [1, true, "three"];

function getItem(n: number) {
  let val: number | boolean | string = tuple[n];
  // ...
}

在元组内设置新值时,新值必须与该索引处的类型匹配。

// @flow
let tuple: [number, boolean, string] = [1, true, "three"];

tuple[0] = 2;     // Works!
tuple[1] = false; // Works!
tuple[2] = "foo"; // Works!

// $ExpectError
tuple[0] = "bar"; // Error!
// $ExpectError
tuple[1] = 42;    // Error!
// $ExpectError
tuple[2] = false; // Error!

严格执行元组长度

元组的长度称为“arity”。在Flow中严格执行元组的长度。

元组只匹配相同长度的元组

他的意思是不能使用较短的元组代替较长的元组。

// @flow
let tuple1: [number, boolean]       = [1, true];
// $ExpectError
let tuple2: [number, boolean, void] = tuple1; // Error!

此外,不能使用较长的元组来代替较短的元组。

// @flow
let tuple1: [number, boolean, void] = [1, true];
// $ExpectError
let tuple2: [number, boolean]       = tuple1; // Error!

元组与数组类型不匹配

由于Flow不知道数组的长度,因此无法将Array <T>类型传递给元组。

// @flow
let array: Array<number>    = [1, 2];
// $ExpectError
let tuple: [number, number] = array; // Error!

另外一个元组类型不能传递给Array <T>类型,因为那样你就可以以不安全的方式改变元组。

// @flow
let tuple: [number, number] = [1, 2];
// $ExpectError
let array: Array<number>    = tuple; // Error!

不能在元组上使用变异数组方法

您不能使用改变元组的Array.prototype方法,只能使用不改变元组的方法。

// @flow
let tuple: [number, number] = [1, 2];
tuple.join(', '); // Works!
// $ExpectError
tuple.push(3);    // Error!

Class类型

Flow中的JavaScript类既可以作为值,也可以作为类型。

您可以像没有Flow一样编写类,但是您可以使用类的名称作为类型。

class MyClass {
  // ...
}

let myInstance: MyClass = new MyClass();

Flow中的类与普通的JavaScript类相同,但添加了类型。

Class 方法

就像在函数中一样,类方法可以有参数(输入)和返回(输出)的注释。

class MyClass {
  method(value: string): number { /* ... */ }
}

class 字段(属性)

每当要在Flow中使用类字段时,必须先给它一个注释。

// @flow
class MyClass {
  method() {
    // $ExpectError
    this.prop = 42; // Error!
  }
}

上面的方式是错误的在flow中。字段在类的主体内注释,字段名称后跟冒号:和类型。

// @flow
class MyClass {
  prop: number;
  method() {
    this.prop = 42;
  }
}

Flow还支持使用类属性语法

class MyClass {
  prop = 42;
}

使用此语法时,不需要为其指定类型注释。但如果你需要,你还可以。

class MyClass {
  prop: number = 42;
}

类泛型

classes 也可以有自己的泛型

class MyClass<A, B, C> {
  property: A;
  method(val: B): C {
    // ...
  }
}

类泛型是参数化的。当您使用类作为类型时,您需要为每个泛型传递参数。

// @flow
class MyClass<A, B, C> {
  constructor(arg1: A, arg2: B, arg3: C) {
    // ...
  }
}

var val: MyClass<number, boolean, string> = new MyClass(1, true, 'three');
上一篇下一篇

猜你喜欢

热点阅读