跳至主要内容

类型转换表达式

有时,在不使用函数或变量的情况下,断言类型很有用。为此,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 运算符与 ininstanceof 具有相同的 优先级。因此,可能需要在表达式周围加上括号

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 关键字进行类型转换,您需要升级您的基础设施,使其支持该语法

有关如何迁移到新转换语法 (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)

注意:括号是必要的,以避免与其他语法产生歧义。