类型转换表达式
有时,在不使用函数或变量的情况下,断言类型很有用。为此,Flow 支持内联类型转换表达式语法,它可以在多种情况下使用。
类型转换表达式语法
为了创建类型转换表达式,请使用关键字 as
将值转换为类型
value as Type
这也可以称为“as 表达式”。
在 Flow 版本 0.229 之前,使用 旧语法
(value: Type)
。
类型转换表达式可以出现在任何表达式可以出现的地方
let val = value as Type;
let obj = {prop: value as Type};
let arr = [value as Type, value as Type] as Array<Type>;
值本身也可以是表达式
12 + 2 as number;
请注意,as
运算符与 in
和 instanceof
具有相同的 优先级。因此,可能需要在表达式周围加上括号
11 === 1 as boolean; // Error! 2// Above same as `1 === (1 as boolean)3
4(1 === 1) as boolean; // Works!
1:7-1:7: Cannot cast `1` to boolean because number [1] is incompatible with boolean [2]. [incompatible-cast]
此外,在表达式语句的上下文中,可能被错误地解析为语句的表达式需要括号
1({a: 1}) as {a: number}; // Needs parens to disambiguate from block statement2const x = {a: 1} as {a: number}; // No parens needed, as not in expression statement context
当您剥离类型时,剩下的只是值
value as Type;
被转换为
value;
类型断言
使用类型转换表达式,您可以断言值是特定类型。
1let value = 42;2
3value as 42; // Works!4value as number; // Works!5value as string; // Error!
5:1-5:5: Cannot cast `value` to string because number [1] is incompatible with string [2]. [incompatible-cast]
以这种方式断言类型与在其他地方使用类型的方式相同。
类型转换
当您编写类型转换表达式时,该表达式的结果是具有提供类型的该值。如果您保留结果值,它将具有新类型。
1let value = 42;2
3value as 42; // Works!4value as number; // Works!5
6let newValue = value as number;7
8newValue as 42; // Error! 9newValue as number; // Works!
8:1-8:8: Cannot cast `newValue` to number literal `42` because number [1] is incompatible with number literal `42` [2]. [incompatible-cast]
不允许不安全的向下转换
1const fooObj = {foo: 1};2const otherObj = fooObj as {foo: number, bar: string}; // ERROR
2:18-2:23: Cannot cast `fooObj` to object type because property `bar` is missing in object literal [1] but exists in object type [2]. [prop-missing]
采用 as
语法
要使用 as
关键字进行类型转换,您需要升级您的基础设施,使其支持该语法
- Flow 和 Flow 解析器:0.229+
- Prettier:3.1+
- Babel:使用 babel-plugin-syntax-hermes-parser 插件版本 0.19+,有关更多详细信息,请参阅我们的 Babel 指南。
- ESLint:使用 hermes-eslint 插件版本 0.19+,有关更多详细信息,请参阅我们的 ESLint 指南。
有关如何迁移到新转换语法 (as
) 的更多详细信息,请查看我们的 博客文章。
使用类型转换表达式
注意:我们将通过一个简化的示例来演示如何使用类型转换表达式。此示例在实践中没有得到很好的解决。
通过 any
进行类型转换
由于类型转换与所有其他类型注解的工作方式相同,因此您只能将值转换为不太具体的类型。您不能更改类型或使其更具体。
但是,您可以使用 any 转换为您想要的任何类型。
1let value = 42;2
3value as number; // Works!4value as string; // Error! 5
6let newValue = value as any as string;7
8newValue as number; // Error! 9newValue as string; // Works!
4:1-4:5: Cannot cast `value` to string because number [1] is incompatible with string [2]. [incompatible-cast]8:1-8:8: Cannot cast `newValue` to number because string [1] is incompatible with number [2]. [incompatible-cast]
通过将值转换为 any
,您就可以转换为您想要的任何类型。
这是不安全的,不推荐。但是,当您对难以或不可能进行类型化的值执行某些操作时,它有时很有用,并且您希望确保结果具有所需的类型。
例如,以下用于克隆对象的函数。
1function cloneObject(obj: any) {2 const clone: {[string]: mixed} = {};3
4 Object.keys(obj).forEach(key => {5 clone[key] = obj[key];6 });7
8 return clone;9}
很难为此创建类型,因为我们根据另一个对象创建了一个新对象。
如果我们通过 any 进行转换,我们可以返回一个更有用的类型。
1function cloneObject<T: {+[key: string]: mixed }>(obj: T): T {2 const clone: {[string]: mixed} = {};3
4 Object.keys(obj).forEach(key => {5 clone[key] = obj[key];6 });7
8 return clone as any as T;9}10
11const clone = cloneObject({12 foo: 1,13 bar: true,14 baz: 'three'15});16
17clone.foo as 1; // Works!18clone.bar as true; // Works!19clone.baz as 'three'; // Works!
旧转换语法
在版本 0.229 之前,要围绕 value
创建类型转换表达式,您需要添加一个冒号 :
以及 Type
,并将表达式用括号 (
)
括起来。
(value: Type)
注意:括号是必要的,以避免与其他语法产生歧义。