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)
-
var arr: Array<number> = [1, 2, 3]
-
arr.push('Hello')
-
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)
-
var obj: { a: string, b: number, c: Array<string>, d: Bar } = {
-
a: 'hello',
-
b: 11,
-
c: ['hello', 'world'],
-
d: new Bar('hello', 3)
-
}
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!
-
// @flow
-
function acceptsNumber(value: number) {
-
// ...
-
}
-
acceptsNumber(42); // Works!
-
acceptsNumber(3.14); // Works!
-
acceptsNumber(NaN); // Works!
-
acceptsNumber(Infinity); // Works!
-
acceptsNumber("foo"); // Error!
-
// @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!
-
// @flow
-
function acceptsNull(value: null) {
-
/* ... */
-
}
-
function acceptsUndefined(value: void) {
-
/* ... */
-
}
-
acceptsNull(null); // Works!
-
acceptsNull(undefined); // Error!
-
acceptsUndefined(null); // Error!
-
acceptsUndefined(undefined); // Works!
-
// @flow
-
function acceptsTwo(value: 2) { //文字值类型声明参数的值
-
// ...
-
}
-
acceptsTwo(2); // Works!
-
// $ExpectError
-
acceptsTwo(3); // Error!
-
// $ExpectError
-
acceptsTwo("2"); // Error!
参数类型是单一类型
-
function square(n: number) {
-
return n * n;
-
}
-
function stringifyBasicValue(value: string | number) {
-
return '' + value;
-
}
-
function identity<T>(value: T): T {
-
return value;
-
}
-
function getTypeOf(value: mixed): string {
-
return typeof value;
-
}
-
// @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");
-
// @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;
-
}
-
}
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!
-
// @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 {
-
// ...
-
}
-
let method = (str, bool, ...nums) => {
-
// ...
-
};
-
-
let method = (str: string, bool?: boolean, ...nums: Array<number>): 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) {
-
// ...
-
}
-
-
-
(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.
-
// @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([]);
-
// @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!
-
// @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 在声明一个对象的属性的时候赋予属性值,那么其属性只能赋给相同类型的变量
-
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!
-
// @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";
在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]
-
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];
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!
-
// @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
-
let array: Array<number> = [0, 1, 2];
-
let value: number | void = array[1];
-
if (value !== undefined) {
-
// number
-
}
-
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!
-
// @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!
-
// @flow
-
let tuple: [number, number] = [1, 2];
-
tuple.join(', '); // Works!
-
// $ExpectError
-
tuple.push(3); // Error!
-
//使用自定义类声明一个变量
-
class MyClass {
-
// ...
-
}
-
let myInstance: MyClass = new MyClass();
-
-
//类函数
-
class MyClass {
-
method(value: string): number { /* ... */ }
-
}
-
// @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');
-
// @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',
-
};
13、Interface Type --- 接口类型
在Flow中,不同的类中有同名属性和函数名是不允许的
-
// @flow
-
class Foo {
-
serialize() { return '[Foo]'; }
-
}
-
class Bar {
-
serialize() { return '[Bar]'; }
-
}
-
// $ExpectError
-
const foo: Foo = new Bar(); // Error!
-
// @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!
-
// @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,
-
}
-
// @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
-
// $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);
-
}
-
}
-
// @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;
-
}
-
// @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];
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 类型不匹配
-