ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## Maybe(可能)类型 Maybe类型用一个`?`在类型前面表示,包含类型本身、`null`、`undefined`。 ``` // @flow /* demo1 */ let hello: ?string; // 声明一个数据类型可以是 string, null, undefined 的变量 hello = null; // 赋值 hello = undefined; // 重新赋值 hello = 'hello'; // 重新赋值 hello = 1; // 报错! hello = true; // 报错! /* demo2 */ function acceptsMaybeString(value: ?string) { // ... } acceptsMaybeString("bar"); // 成功! acceptsMaybeString(undefined); // 成功! acceptsMaybeString(null); // 成功! acceptsMaybeString(); // 成功! ``` </br> ## Optional(可选)类型 >Optional一般用于对象属性或者函数参数,在名称后面加一个`?`,包含类型本身、`undefined`,注意,这里不包括`null`类型。 **可选的对象属性** 即对象类型可以具有可选属性,问号`?`位于属性名称后面。 ``` { propertyName?: string } ``` 除了它们的设定值类型之外,这些可选属性也可以被`void`完全省略。但是不能是`null`。 ``` // @flow function acceptsObject(value: { foo?: string }) { // ... } acceptsObject({ foo: "bar" }); // 成功! acceptsObject({ foo: undefined }); // 成功! acceptsObject({ foo: null }); // 报错! acceptsObject({ foo: true}); // 报错! acceptsObject({}); // 成功! ``` **可选的函数参数** 即函数可以具有可选参数,其中问号`?`出现在参数名称后面。同样,该参数不能为`null`。 ``` // @flow function acceptsOptionalString(value?: string) { // ... } acceptsOptionalString("bar"); // 成功! acceptsOptionalString(undefined); // 成功! acceptsOptionalString(null); // 报错! acceptsOptionalString(); // 成功! ``` </br> ## Literal(字面文字)类型 >字面文字类型指的是以真实值作为数据类型,可用的值有三种,即数字、字符串或布尔值。 ``` // @flow /* demo1 */ let hello: 'hello'; // 声明一个只能赋值 'hello' 的变量 hello = 'hello'; // 赋值成功! hello = 'hi'; // 报错! hello = 12; // 报错! hello = undefined; // 报错! hello = null; // 报错! /* demo2 */ function method(param: 1 | 'hi' | boolean): void { /* ... */ } method(); // 报错,缺少参数 method(1); // 成功! method(1.2); // 报错,类型不对 method('hi'); // 成功! method('hello'); // 报错,类型不对 method(true); // 成功! method(false); // 成功! ``` </br> ## Mixed(混合)类型 Mixed类型是指任意数据类型。 ``` // @flow let hello: mixed; // 声明一个 mixed 类型的变量 hello = 'hello'; // 赋值 hello = true; // 重新赋值 hello = 12; // 重新赋值 hello = undefined; // 重新赋值 hello = null; // 重新赋值 ``` 有时候我们并不能确定需要的值到底是哪种类型,这时候我们可以使用混合类型来表示,但在使用该值之前,我们需要判断该值到底是哪种类型,否则会引起错误。 ``` // @flow function stringify(value: mixed) { return "" + value; } stringify("foo"); ``` 如上面代码,运行之后就报错了, > Error ----------------------------------------------------------------------------------------------- src/index.js:12:10 > Cannot add empty string and `value` because mixed [1] could either behave like a string or like a number. >  src/index.js:12:10 >  12| return "" + value; // Error! >      ^^^^^^^^^^ >References: >  src/index.js:10:27 >  10| function stringify(value: mixed) { >              ^^^^^ [1] >Found 1 error 原因是虽然输入时可以用`mixed`,但Flow会认为函数中`value`的值不见得可以与`string`类型作相加,所以会请求你要在函数中的代码,要加入检查对传入类型在运行期间的类型检查代码,例如像下面修改过才能过关: ``` // @flow function stringify(value: mixed) { if (typeof value === 'string' || typeof value === 'number') { return "" + value; } else { return value; } } stringify("foo"); ``` 从上面的例子可以看到Flow除了对类型会作检查外,它也会请求对某些类型需要有动态的检查。在官方的文件可以参考[Type Refinements](https://flow.org/en/docs/lang/refinements/#_)这个章节。 </br> ## Any(任意)类型 如果你想要一种方法来选择不使用类型检查器,或是还在开发中正在调试时,有一种作为渐进的改善代码的类型。 `Any`类型就可以做到这一点。但是切记,使用`Any`是不安全的,因为会失去类型检查,应尽可能避免使用。 例如,下面的代码不会报告任何提示: ``` // @flow function add(one: any, two: any): number { return one + two; } add(1, 2); // 成功! add("1", "2"); // 成功! add("1", 2); // 成功! add({}, []); // 成功! ``` 当然还不止上面的问题,使用`Any`类型还可能会出现即使是会导致运行时错误的代码也不会被Flow捕获。 ``` // @flow function getObjProperty(obj: any) { return obj.a.b; } getObjProperty({}); // No Errors ! ``` 上面这段代码明显错误(Uncaught TypeError: Cannot read property 'b' of undefined),但是由于`Any`类型的存在,Flow并没有捕捉到错误,反而通过了检查。 </br> ## Type Alias(类型别名) `Type Alias`提供了可以预先定义与集中代码中所需要的类型,一个简单的例子如下: ``` // @flow type T = Array<string>; let x: T = []; x["Hi"] = 2; // 报错! ``` `Type Alias`也可以用于复杂的应用情况,详见Flow官网提供的[Type Aliases](https://flowtype.org/docs/type-aliases.html)这一章节。 ## Union(联合)类型 所有的类型都可以使用垂直线符号`|`作为联合使用(也就是 OR 的意思),例如`string | number`指的是两种类型其中一种都可使用,这是一种联合的类型,称为`Union`类型。 ``` // @flow type U = number | string; let x: U = 1; // 成功! x = "two"; // 成功! x = true; // 报错! ``` </br>