flow类型检查
https://blog.csdn.net/tangxiujiang/article/details/80778627
Flow的简单介绍
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)函数的类型注释
- function add(x: number, y: number): number {
- return x + y //x的类型是number,y的类型是number,函数的返回值类型是number
- }
- add('Hello', 11)
2)数组类型注释:Array<T>,T表示数组中每项的数据类型
- var arr: Array<number> = [1, 2, 3]
- arr.push('Hello')
3)类类型注释
- class Bar {
- x: string; // x 是字符串
- y: string | number; // y 可以是字符串或者数字
- z: boolean;
- constructor(x: string, y: string | number) {
- this.x = x
- this.y = y
- this.z = false
- }
- }
- var bar: Bar = new Bar('hello', 4)
4)对象类型注释
- var obj: { a: string, b: number, c: Array<string>, d: Bar } = {
- a: 'hello',
- b: 11,
- c: ['hello', 'world'],
- d: new Bar('hello', 3)
- }
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、类型是文字的小写字母开头的
- // @flow
- function method(x: number, y: string, z: boolean) {
- // ...
- }
- method(3.14, "hello", true);
- 2、类型是大写字母开头的
- // @flow
- function method(x: Number, y: String, z: Boolean) {
- // ...
- }
- method(new Number(42), new String("world"), new Boolean(false));
1)Boolean:在Flow中,参数为boolean类型只有false true两个值
- // @flow
- function acceptsBoolean(value: boolean) {
- // ...
- }
- acceptsBoolean(true); // Works!
- acceptsBoolean(false); // Works!
- acceptsBoolean("foo"); // Error!
- 做简单的转换
- if (42) {} // 42 => true
- if ("") {} // "" => false
- 如果参数是boolean类型,使用的时候参数为数值类型需要转换成非Boolean类型,Boolean(x) 或者 !!x
- // @flow
- function acceptsBoolean(value: boolean) {
- // ...
- }
- acceptsBoolean(0); // Error!
- acceptsBoolean(Boolean(0)); // Works!
- acceptsBoolean(!!0); // Works!
2)Number:在js中认为NaN Infinity也是数字
- // @flow
- function acceptsNumber(value: number) {
- // ...
- }
- acceptsNumber(42); // Works!
- acceptsNumber(3.14); // Works!
- acceptsNumber(NaN); // Works!
- acceptsNumber(Infinity); // Works!
- acceptsNumber("foo"); // Error!
3)String:在Flow中变量声明为string类型只接受string类型;两个变量相加的时候,只接受string和number的拼接,其他类型需要显示的转化为string类型
- // @flow
- function acceptsString(value: string) {
- // ...
- }
- acceptsString("foo"); // Works! 只接受字符串类型
- acceptsString(false); // Error!
- // @flow 两个变量相加的时候,只接受string和number的拼接
- "foo" + "foo"; // Works!
- "foo" + 42; // Works!
- "foo" + {}; // Error!
- "foo" + []; // Error!
- // @flow 其他类型需要显示的转化为String类型
- "foo" + String({}); // Works!
- "foo" + [].toString(); // Works!
- "" + JSON.stringify({}) // Works!
4)null 和void(undefined):在js中的类型是null和undefined,但是在Flow中是null和void
- // @flow
- function acceptsNull(value: null) {
- /* ... */
- }
- function acceptsUndefined(value: void) {
- /* ... */
- }
- acceptsNull(null); // Works!
- acceptsNull(undefined); // Error!
- acceptsUndefined(null); // Error!
- acceptsUndefined(undefined); // Works!
2、Literal Types---文字值类型
- // @flow
- function acceptsTwo(value: 2) { //文字值类型声明参数的值
- // ...
- }
- acceptsTwo(2); // Works!
- // $ExpectError
- acceptsTwo(3); // Error!
- // $ExpectError
- acceptsTwo("2"); // Error!
3、Mixed Types---混合类型
参数类型是单一类型
- function square(n: number) {
- return n * n;
- }
参数类型是不同类型,使用|来声明
- function stringifyBasicValue(value: string | number) {
- return '' + value;
- }
一种类型依赖于另一种类型,函数的返回值类型依赖于参数值的类型
- function identity<T>(value: T): T {
- return value;
- }
使用mixed声明参数的类型,即参数的类型是未知的
- function getTypeOf(value: mixed): string {
- return typeof value;
- }
mixed类型可以是任意类型,但是在使用该类型的参数进行运算的时候,需要判断他的具体类型,否则则会报错
- // @flow mixed类型的参数可以是任意类型
- function stringify(value: mixed) {
- // ...
- }
- stringify("foo");
- stringify(3.14);
- stringify(null);
- stringify({});
- // @flow 在使用mixed类型的参数进行运算的时候,需要判断他的类型
- 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");
4、Any Types---任意类型(谨慎使用)
- // @flow 不会去判断类型,任意类型都可以在一起运算
- function add(one: any, two: any): number {
- return one + two;
- }
- add(1, 2); // Works.
- add("1", "2"); // Works.
- add({}, []); // Works.
5、Maybe Types---可能的类型,使用?标记
- // @flow 比如?number---表示参数类型可以是number null undefined
- function acceptsMaybeNumber(value: ?number) {
- // ...
- }
- acceptsMaybeNumber(42); // Works!
- acceptsMaybeNumber(); // Works!
- acceptsMaybeNumber(undefined); // Works!
- acceptsMaybeNumber(null); // Works!
- acceptsMaybeNumber("42"); // Error!
- // @flow 如果在Maybe Types中想使用的是number类型,那么需要先判断其为number类型,然后再进行处理
- function acceptsMaybeNumber(value: ?number) {
- if (value !== null && value !== undefined) { //比较复杂的判断
- return value * 2;
- }
- }
- // @flow
- function acceptsMaybeNumber(value: ?number) {
- if (value != null) { // 使用 != 来比较
- return value * 2;
- }
- }
- // @flow
- function acceptsMaybeNumber(value: ?number) {
- if (typeof value === 'number') { // 使用===来判断
- return value * 2;
- }
- }
6、Variable Types---变量类型
js中有3种方法声明变量,分别是var let const
var---声明的变量有提升的作用,可以重新赋值
let---声明块级作用域的变量,可以重新赋值
const---声明块级作用域的变量,声明的时候要初始化,不可以重新赋值
- // @flow
- const foo /* : number */ = 1;
- const bar: number = 2;
- // @flow 当在声明一个变量的时候提供类型注释,那么在重新赋值的时候,也只能赋予 相同类型的值
- let foo: number = 1;
- foo = 2; // Works!
- // $ExpectError
- foo = "3"; // Error!
- //当在声明一个类型的时候,没有使用类型注释,那么在改变变量的类型的时候,在声明另一个类型的时候,需要给这个类型提供所有的类型注释
- let foo = 42;
- if (Math.random()) foo = true;
- if (Math.random()) foo = "hello";
- let isOneOf: number | boolean | string = foo; // Works!
- // @flow 在if语句、函数和其他条件代码块里面,Flow不能判断变量改变之后的类型
- let foo = 42;
- function mutate() {
- foo = true;
- foo = "hello";
- }
- mutate();
- // $ExpectError
- let isString: string = foo; // Error!
7、Function Types---函数类型 ,在参数和返回值的类型注释
- // @flow
- function concat(a: string, b: string): string {
- return a + b;
- }
- concat("foo", "bar"); // Works!
- // $ExpectError
- concat(true, false); // Error!
设置可选参数:param?:type ,参数可以没有设置、undefined、match type,但不能为null
- // @flow
- function method(optionalValue?: string) {
- // ...
- }
- method(); // Works.
- method(undefined); // Works.
- method("string"); // Works.
- // $ExpectError
- method(null); // Error!
在Flow中有3种类型的函数类型声明
1)函数声明
- function method(str, bool, ...nums) {
- // ...
- }
- function method(str: string, bool?: boolean, ...nums: Array<number>): void {
- // ...
- }
2)箭头函数
- let method = (str, bool, ...nums) => {
- // ...
- };
- let method = (str: string, bool?: boolean, ...nums: Array<number>): void => {
- // ...
- };
3)函数类型
- (str: string, bool?: boolean, ...nums: Array<number>) => void
- //可以省略参数名
- (string, boolean | void, Array<number>) => void
- //设置回调函数
- function method(callback: (error: Error | null, value: string | null) => void) {
- // ...
- }
- (str: string, bool?: boolean, ...nums: Array<number>) => void
- //可以省略参数名
- (string, boolean | void, Array<number>) => void
- //设置回调函数
- function method(callback: (error: Error | null, value: string | null) => void) {
- // ...
- }
rest参数: ... 必须为数组,且放在参数的最后面
- // @flow
- function method(...args: Array<number>) {
- // ...
- }
- method(); // Works.
- method(1); // Works.
- method(1, 2); // Works.
- method(1, 2, 3); // Works.
函数返回值: 通过 :type 设置 注意设置了返回值类型,就一定要return该类型,否则报错
- // @flow
- // $ExpectError
- function method(): boolean {
- if (Math.random() > 0.5) { //对于不符合if语句的话,函数会返回undefined,和boolean类型不匹配,所以报错
- return true;
- }
- }
函数中的this:在Flow中胡会自动识别this的上下文环境
- function method() {
- return this;
- }
- var num: number = method.call(42);
- // $ExpectError
- var str: string = method.call(42);
谓词函数:%check
- //报错
- function truthy(a, b): boolean {
- return a && b;
- }
- function concat(a: ?string, b: ?string): string {
- if (truthy(a, b)) {
- // $ExpectError
- return a + b;
- }
- return '';
- }
- //修正
- function truthy(a, b): boolean %checks {
- return !!a && !!b;
- }
- function concat(a: ?string, b: ?string): string {
- if (truthy(a, b)) {
- return a + b;
- }
- return '';
- }
- function isString(y): %checks {
- return typeof y === "string";
- }
- function isNumber(y): %checks {
- return typeof y === "number";
- }
- function isNumberOrString(y): %checks {
- return isString(y) || isNumber(y);
- }
- function foo(x): string | number {
- if (isNumberOrString(x)) {
- return x + x;
- } else {
- return x.length; // no error, because Flow infers that x can only be an array
- }
- }
- foo('a');
- foo(5);
- foo([]);
8、Object Types---对象类型
- // @flow
- var obj1: { foo: boolean } = { foo: true };
- var obj2: {
- foo: number,
- bar: boolean,
- baz: string,
- } = {
- foo: 1,
- bar: true,
- baz: 'three',
- };
在js中访问对象不存在的属性会得到undefined,而在Flow里面访问对象不存在的属性,会报错
- // @flow 在js中访问对象不存在的属性会得到undefined,而在Flow里面访问对象不存在的属性,会报错
- var obj = { foo: "bar" };
- // $ExpectError
- obj.bar; // Error!
可以通过设置 属性名?:type 来设置属性为void / omitted / match type 但不能为null
- // @flow 可以通过设置 属性名?:type 来设置属性为void / omitted / match type 但不能为null
- var obj: { foo?: boolean } = {};
- obj.foo = true; // Works!
- // $ExpectError
- obj.foo = 'hello'; // Error!
- // @flow
- function acceptsObject(value: { foo?: string }) {
- // ...
- }
- acceptsObject({ foo: "bar" }); // Works!
- acceptsObject({ foo: undefined }); // Works!
- // $ExpectError
- acceptsObject({ foo: null }); // Error!
- acceptsObject({}); // Works!
当在Flow中声明一个对象的属性的值的时候,Flow会直到属性的类型,对象的属性值只能赋给同类型的变量,同时在这种情况下不能另外声明属性
- // @flow 在声明一个对象的属性的时候赋予属性值,那么其属性只能赋给相同类型的变量
- var obj = {
- foo: 1,
- bar: true,
- baz: 'three'
- };
- var foo: number = obj.foo; // Works!
- var bar: boolean = obj.bar; // Works!
- // $ExpectError
- var baz: null = obj.baz; // Error!
- var bat: string = obj.bat; // Error!
- // $ExpectError 在这种况下不能再声明其他属性
- obj.bass = true; // Error!
- // $ExpectError
- obj.bahhh = 'three'; // Error!
声明变量的时候没有赋予对象任何属性,此时可以添加额外的属性
- // @flow
- var obj = {};
- obj.foo = 1; // Works!
- obj.bar = true; // Works!
- obj.baz = 'three'; // Works!
给unsealed object重新赋值的时候,将其属性值赋予给另一个变量,此时该变量要列出所有该对象的属性type
- // @flow
- var obj = {};
- if (Math.random()) obj.prop = true;
- else obj.prop = "hello";
- // $ExpectError
- var val1: boolean = obj.prop; // Error!
- // $ExpectError
- var val2: string = obj.prop; // Error!
- var val3: boolean | string = obj.prop; // Works!
能推断对象属性的类型
- var obj = {};
- obj.foo = 1;
- obj.bar = true;
- var foo: number = obj.foo; // Works!
- var bar: boolean = obj.bar; // Works!
- var baz: string = obj.baz; // Works?
宽子类型
- // @flow
- function method(obj: { foo: string }) {
- // ...
- }
- method({
- foo: "test", // Works!
- bar: 42 // Works!
- });
索引属性
- // @flow
- var o: { [string]: number } = {};
- o["foo"] = 0;
- o["bar"] = 1;
- var foo: number = o["foo"];
- // @flow
- var obj: { [user_id: number]: string } = {};
- obj[1] = "Julia";
- obj[2] = "Camille";
- obj[3] = "Justin";
- obj[4] = "Mark";
9、Array Types---数组类型
在js中的Array的定义如下所示:
- new Array(1, 2, 3); // [1, 2, 3];
- new Array(3); // [undefined, undefined, undefined]
- [1, 2, 3]; // [1, 2, 3];
- let arr = []; // []
- arr[0] = 1; // [1]
- arr[1] = 2; // [1, 2]
- arr[2] = 3; // [1, 2, 3]
使用 param: Array<type>来声明数组类型,其中type是数组元素的类型
- let arr1: Array<boolean> = [true, false, true];
- let arr2: Array<string> = ["A", "B", "C"];
- let arr3: Array<mixed> = [1, true, "three"]
- let arr: Array<number> = [1, 2, 3];
使用精简的写法:type[]
let arr: number[] = [0, 1, 2, 3];
?type[] = ? Array<type>:表示元素成员可以match type,或者整个为null
- // @flow
- let arr1: ?number[] = null; // Works!
- let arr2: ?number[] = [1, 2]; // Works!
- let arr3: ?number[] = [null]; // Error!
Array<?type> = (?type)[]:表示成员可以为null、match type
- // @flow
- let arr1: (?number)[] = null; // Error!
- let arr2: (?number)[] = [1, 2]; // Works!
- let arr3: (?number)[] = [null]; // Works!
当访问数组的元素超过数组的索引,那么在Flow中会标记其值为undefined
- // @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
- let array: Array<number> = [0, 1, 2];
- let value: number | void = array[1];
- if (value !== undefined) {
- // number
- }
9、Tuple Types---元祖类型 [type,type,type] 元祖使用数组声明
- let tuple1: [number] = [1];
- let tuple2: [number, boolean] = [1, true];
- let tuple3: [number, boolean, string] = [1, true, "three"];
从元祖中通过索引去获取元祖元素的时候,在Flow中会返回该元素类型的值
- // @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!
如果访问一个超出索引的元祖的元素的时候,Flow会返回一个void值
- // @flow
- let tuple: [number, boolean, string] = [1, true, "three"];
- let none: void = tuple[3];
如果不确定返回元祖的那个索引的值,那么在用元祖的元素去赋值给的另一个变量的时候要列出元祖的所有类型
- // @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!
元祖的长度称为元数,短的元祖不能赋值给长的元数,长的元祖不能赋值给短的元数,即只有元数相同的时候才能赋值
- // @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
- let array: Array<number> = [1, 2];
- // $ExpectError
- let tuple: [number, number] = array; // Error!
- // @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!
10、Class Types---类类型
- //使用自定义类声明一个变量
- class MyClass {
- // ...
- }
- let myInstance: MyClass = new MyClass();
- //类函数
- class MyClass {
- method(value: string): number { /* ... */ }
- }
在Flow中使用公有属性的时候,必须先声明他的类型
- // @flow 错误
- class MyClass {
- method() {
- // $ExpectError
- this.prop = 42; // Error!
- }
- }
- // @flow 正确
- class MyClass {
- prop: number;
- method() {
- this.prop = 42;
- }
- }
直接声明属性:下面两种写法都是正确的
- class MyClass {
- prop = 42;
- }
- class MyClass {
- prop: number = 42;
- }
类泛型:给类的属性指定里面一共有哪些数据类型,在赋值的时候才给出明确的类型
- // @flow
- class MyClass<A, B, C> {
- constructor(arg1: A, arg2: B, arg3: C) {
- // ...
- }
- }
- var val: MyClass<number, boolean, string> = new MyClass(1, true, 'three');
11、Type Aliase---类型别名 使用type param = type 来声明,声明的类型别名可以用在任何地方
- // @flow
- type MyObject = {
- foo: number,
- bar: boolean,
- baz: string,
- };
- var val: MyObject = { /* ... */ };
- function method(val: MyObject) { /* ... */ }
- class Foo { constructor(val: MyObject) { /* ... */ } }
- type NumberAlias = number;
- type ObjectAlias = {
- property: string,
- method(): number,
- };
- type UnionAlias = 1 | 2 | 3;
- type AliasAlias = ObjectAlias;
类型别名泛型
- // @flow
- type MyObject<A, B, C> = {
- foo: A,
- bar: B,
- baz: C,
- };
- var val: MyObject<number, boolean, string> = {
- foo: 1,
- bar: true,
- baz: 'three',
- };
12、Opaque Type Aliase--- 不透明类型别名
13、Interface Type --- 接口类型
在Flow中,不同的类中有同名属性和函数名是不允许的
- // @flow
- class Foo {
- serialize() { return '[Foo]'; }
- }
- class Bar {
- serialize() { return '[Bar]'; }
- }
- // $ExpectError
- const foo: Foo = new Bar(); // Error!
可以使用interface来声明一个接口
- // @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!
使用implements去匹配接口,可以使用多个接口
- class Foo implements Bar, Baz {
- // ...
- }
- // @flow
- interface Serializable {
- serialize(): string;
- }
- class Foo implements Serializable {
- serialize() { return '[Foo]'; } // Works!
- }
- class Bar implements Serializable {
- // $ExpectError
- serialize() { return 42; } // Error!
- }
- //接口函数
- interface MyInterface {
- method(value: string): number;
- }
- //接口属性
- interface MyInterface {
- property: string;
- }
- interface MyInterface {
- property?: string;
- }
- //接口映射
- interface MyInterface {
- [key: string]: number;
- }
- 接口泛型
- / @flow
- interface MyInterface<A, B, C> {
- foo: A;
- bar: B;
- baz: C;
- }
- var val: MyInterface<number, boolean, string> = {
- foo: 1,
- bar: true,
- baz: 'three',
- };
- //接口属性:只读(+) 只写(-)
- // @flow 只读+
- interface Invariant { property: number | string }
- interface Covariant { +readOnly: number | string }
- function method1(value: Invariant) {
- value.property; // Works!
- value.property = 3.14; // Works!
- }
- function method2(value: Covariant) {
- value.readOnly; // Works!
- // $ExpectError
- value.readOnly = 3.14; // Error!
- }
- //只写 -
- interface Invariant { property: number }
- interface Contravariant { -writeOnly: number }
- function method1(value: Invariant) {
- value.property; // Works!
- value.property = 3.14; // Works!
- }
- function method2(value: Contravariant) {
- // $ExpectError
- value.writeOnly; // Error!
- value.writeOnly = 3.14; // Works!
}14、Generic Type --- 泛型类型
- // @flow
- type IdentityWrapper = {
- func<T>(T): T
- }
- function identity(value) {
- return value;
- }
- function genericIdentity<T>(value: T): T {
- return value;
- }
- // $ExpectError
- const bad: IdentityWrapper = { func: identity }; // Error!
- const good: IdentityWrapper = { func: genericIdentity }; // Works!
函数泛型
- //1
- function method<T>(param: T): T {
- // ...
- }
- //2
- function<T>(param: T): T {
- // ...
- }
- //3
- <T>(param: T) => T
- //4
- function method(func: <T>(param: T) => T) {
- // ...
- }
类泛型
- class Item<T> {
- prop: T;
- constructor(param: T) {
- this.prop = param;
- }
- method(): T {
- return this.prop;
- }
- }
类型别名泛型
- type Item<T> = {
- foo: T,
- bar: T,
- };
接口泛型
- interface Item<T> {
- foo: T,
- bar: T,
- }
15、Union Type --- 并集类型 type1 | type2 | type3
- // @flow
- function toStringPrimitives(value: number | boolean | string) {
- return String(value);
- }
- toStringPrimitives(1); // Works!
- toStringPrimitives(true); // Works!
- toStringPrimitives('three'); // Works!
- // $ExpectError
- toStringPrimitives({ prop: 'val' }); // Error!
- // $ExpectError
- toStringPrimitives([1, 2, 3, 4, 5]); // Error!
多行声明
- type Foo =
- | Type1
- | Type2
- | ...
- | TypeN
声明多种类型
- type Numbers = 1 | 2;
- type Colors = 'red' | 'blue'
- type Fish = Numbers | Colors;
在函数中使用并集的时候,需要对所有类型进行处理,否则Flow会报错
- // @flow
- // $ExpectError 没有对参数是string类型的进行处理,所以Flow报错
- function toStringPrimitives(value: number | boolean | string): string { // Error!
- if (typeof value === 'number') {
- return String(value);
- } else if (typeof value === 'boolean') {
- return String(value);
- }
- }
15、Intersection Type --- 交集类型 type1 & type2 & type3 参数里面必须书写所有的变量类型
- // @flow
- type A = { a: number };
- type B = { b: boolean };
- type C = { c: string };
- function method(value: A & B & C) {
- // ...
- }
- // $ExpectError
- method({ a: 1 }); // Error!
- // $ExpectError
- method({ a: 1, b: true }); // Error!
- method({ a: 1, b: true, c: 'three' }); // Works!
在多行声明
- type Foo =
- & Type1
- & Type2
- & ...
- & TypeN
- type Foo = Type1 & Type2;
- type Bar = Type3 & Type4;
- type Baz = Foo & Bar;
- // @flow
- type A = { a: number };
- type B = { b: boolean };
- type C = { c: string };
- function method(value: A & B & C) {
- var a: A = value;
- var b: B = value;
- var c: C = value;
- }
16、typeof Type --- 类型检测 typeof 返回一个给定值的类型
- // @flow
- let num1 = 42;
- let num2: typeof num1 = 3.14; // Works!
- // $ExpectError
- let num3: typeof num1 = 'world'; // Error!
- let bool1 = true;
- let bool2: typeof bool1 = false; // Works!
- // $ExpectError
- let bool3: typeof bool1 = 42; // Error!
- let str1 = 'hello';
- let str2: typeof str1 = 'world'; // Works!
- // $ExpectError
- let str3: typeof str1 = false; // Error!
如果是文字类型的话,就会报错
- // @flow
- let num1: 42 = 42;
- // $ExpectError
- let num2: typeof num1 = 3.14; // Error!
- let bool1: true = true;
- // $ExpectError
- let bool2: typeof bool1 = false; // Error!
- let str1: 'hello' = 'hello';
- // $ExpectError
- let str2: typeof str1 = 'world'; // Error!
- // @flow
- let obj1 = { foo: 1, bar: true, baz: 'three' };
- let obj2: typeof obj1 = { foo: 42, bar: false, baz: 'hello' };
- let arr1 = [1, 2, 3];
- let arr2: typeof arr1 = [3, 2, 1];
17、Type Casting Expressions --- 类型透射表达式 (value : type)
18、Utility Type
19、Module Types
20、Common Types
- // @flow
- /*::
- type MyAlias = {
- foo: number,
- bar: boolean,
- baz: string,
- };
- */
- function method(value /*: MyAlias */) /*: boolean */ {
- return value.bar;
- }
- method({ foo: 1, bar: true, baz: ["oops"] }); //error 类型不匹配
flow类型检查的更多相关文章
- 在vue中配置flow类型检查
flow中文文档:https://zhenyong.github.io/flowtype/docs/objects.html#_ 1.安装flow npm install --save-dev flo ...
- vue项目配置使用flow类型检查
你是否经常在debug那些简单可避免的bug?可能你给函数传参的时候搞错了参数的顺序,或者本来应该传个Number类型的参数,你传了一个String类型?JavaScript的弱类型是这一类bug的罪 ...
- Flow: JavaScript静态类型检查工具
Flow: JavaScript静态类型检查工具 Flow是Facebook出品的,针对JavaScript的静态类型检查工具.其代码托管在github之上,并遵守BSD开源协议. 关于Flow 它可 ...
- flow 静态类型检查 js
1.flow介绍 https://ustbhuangyi.github.io/vue-analysis/prepare/flow.html#为什么用-flow 2.使用 (1)安装flow (2)项目 ...
- 理解Flow静态类型检查
一.为什么在JavaScript中使用静态类型 了解静态类型的最快方法是将其与动态类型进行对比. 有静态类型参数的语言被称为静态类型语言. 另一方面,有动态类型参数的语言被称为动态类型语言.核心区别是 ...
- 如何使用flow进行静态类型检查
Flow 是 facebook 出品的 JavaScript 静态类型检查⼯具.Vue.js 的源码利⽤了 Flow 做了静态类型检查,所以了解 Flow 有助于我们阅读源码. 为什么⽤ Flow? ...
- 编译期类型检查 in ClojureScript
前言 话说"动态类型一时爽,代码重构火葬场",虽然有很多不同的意见(请参考),但我们看到势头强劲的TypeScript和Flow.js,也能感知到静态类型在某程度上能帮助我们写出 ...
- React文档(十五)使用propTypes进行类型检查
注意: React.PropTypes 自 React v15.5 起已弃用.请使用 prop-types 库代替. 随着你的应用的开发,你会使用类型检查的方法来捕获很多bug.对于一些应用,你可以使 ...
- 编译器开发系列--Ocelot语言6.静态类型检查
关于"静态类型检查",想必使用C 或Java 的各位应该非常熟悉了.在此过程中将检查表达式的类型,发现类型不正确的操作时就会报错.例如结构体之间无法用+ 进行加法运算,指针和数值之 ...
随机推荐
- python中return的用法
def testReturn(x): if x > 10000: return print "test return!!" #这句话永远不会得到执行 elif x > ...
- Reconstruction(三维重建)文件被修改
修改内容: 该函数被修改了一部分,然后修改中止了,可能是牵一发而动全身,导致中止.无论什么原因,这个Reconstruction.cpp文件是唯一被修改的文件了.如果没有被修改该多好!!!!!! 如何 ...
- mongoexport遭遇Authentication failed
今天使用mongoexport工具导出数据,遇到权限不足报错:[host]$mongoexport -h 10.31.11.190:23820 -udbmgr -pMgr2mgdb -d rcmp ...
- DbSet中Find,AsNoTracking,Attach及DBEntityEntry,ChangeTracker
Find,AsNoTracking,Attach,DBEntityEntry,ChangeTracker,Local 一:DBSet 我们在SaveChange的时候,如果获取到DbSet中一些Ent ...
- Verilog MIPS32 CPU(三)-- ALU
Verilog MIPS32 CPU(一)-- PC寄存器 Verilog MIPS32 CPU(二)-- Regfiles Verilog MIPS32 CPU(三)-- ALU Verilog M ...
- EF修改model自动更新数据库
最近用MVC+EF学习时遇到修改model后而数据库没更新报错,就在网上找关于数据迁移自动更新数据库的,折腾了大半天终于弄了出来 第一步:在程序包管理器控制台里: Enable-Migrations ...
- 如何执行oracle存储过程,就exec一下?
不单单是exec一下,还是得分情况: 1.如果是命令窗口就用exec 存储过程名,举个栗子: EXEC procedure;--procedure是存储过程名 2.如果是PL/SQL窗口就用 begi ...
- jenkins+docker+docker machine 远程部署
dotnet publish -c Release docker build -t microtest:1.0 --build-arg microport=1000 -f "$WORKSPA ...
- Qt学习(二):项目学习
1. 概述 Qt做UI设计后,通常会生成Form Files文件夹下的ui文件.Generated File文件夹下的ui_xxx等头文件和源文件.Header Files文件夹下的头文件.Sourc ...
- 【QTP小技巧】02_QTP中Complete Word 实现(转载)
相信做过开发或者写过JAVA的朋友都应该对Complete Word这个词语不陌生吧~ 对~~~它就是开发脚本过程中的催化剂 有了它我们就可以不用去死记硬背 有了它我们就不会出现某个代码少一个字母 有 ...