Skip to main content

类型转换表达式

有时,不使用函数或变量之类的东西来断言类型是有用的。为此,Flow 支持内联类型转换表达式语法,可以通过多种不同方式使用该语法。

¥Sometimes it is useful to assert a type without using something like a function or a variable to do so. For this Flow supports an inline type cast expression syntax which can be used in a number of different ways.

类型转换表达式语法

¥Type Cast Expression Syntax

为了创建类型转换表达式,请使用关键字 as 将值转换为类型:

¥In order to create a type cast expression, use the keyword as to cast the value to a type:

value as Type

这也可以称为 "作为表达式"。

¥This can also be referred to as an "as expression".

Flow 版本 0.229 之前,使用的是 旧版语法 (value: Type)

¥Before Flow version 0.229, the legacy syntax (value: Type) was used.

类型转换表达式可以出现在任何可以出现表达式的地方:

¥Type cast expressions can appear anywhere an expression can appear:

let val = value as Type;
let obj = {prop: value as Type};
let arr = [value as Type, value as Type] as Array<Type>;

该值本身也可以是一个表达式:

¥The value itself can also be an expression:

12 + 2 as number;

请注意,as 运算符具有与 ininstanceof 相同的 precedence。因此,可能需要将表达式括起来的括号:

¥Note that the as operator has the same precedence as in and instanceof. Because of this, parentheses around the expression might be required:

11 === 1 as boolean; // Error!2// Above same as `1 === (1 as boolean)3
4(1 === 1) as boolean; // Works!

此外,当在表达式语句的上下文中时,可能不明确地解析为语句的表达式需要括号:

¥Additionally, when in the context of an expression statement, expressions which could ambiguously parse as statements need parens:

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

当你剥离类型时,剩下的就是值:

¥When you strip the types all that is left is the value:

value as Type;

转化为:

¥Is transformed into:

value;

类型断言

¥Type Assertions

使用类型转换表达式,你可以断言值是某些类型。

¥Using type cast expressions you can assert that values are certain types.

1let value = 42;2
3value as 42;     // Works!4value as number; // Works!5value as string; // Error!

以这种方式断言类型的工作方式与类型在其他地方的工作方式相同。

¥Asserting types in this way works the same as types do anywhere else.

类型铸造

¥Type Casting

当你编写类型转换表达式时,该表达式的结果是具有所提供类型的值。如果保留结果值,它将具有新类型。

¥When you write a type cast expression, the result of that expression is the value with the provided type. If you hold onto the resulting value, it will have the new type.

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!

不允许不安全的向下转型:

¥Unsafe downcasts are not allowed:

1const fooObj = {foo: 1};2const otherObj = fooObj as {foo: number, bar: string};  // ERROR

采用 as 语法

¥Adoption of as syntax

要使用 as 关键字进行类型转换,你需要升级基础架构以使其支持以下语法:

¥To use the as keyword for type casts, you need to upgrade your infrastructure so that it supports the syntax:

有关如何迁移到新的转换语法 (as) 的更多详细信息,请查看我们的 博客文章

¥For more details on how to migrate to the new casting syntax (as) check out our blog post.

使用类型转换表达式

¥Using type cast expressions

注意:我们将通过一个精简的示例来演示如何使用类型转换表达式。这个例子在实际中并没有很好的解决。

¥Note: We're going to go through a stripped down example for demonstrating how to make use of type cast expressions. This example is not solved well in practice.

通过 any 进行类型转换

¥Type Casting through any

由于类型转换的工作方式与所有其他类型注释相同,因此你只能将值转换为不太具体的类型。你无法更改类型或使其变得更具体。

¥Because type casts work the same as all other type annotations, you can only cast values to less specific types. You cannot change the type or make it something more specific.

但你可以使用 任何 转换为你想要的任何类型。

¥But you can use any to cast to whatever type you want.

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!

通过将该值转换为 any,你就可以转换为你想要的任何值。

¥By casting the value to any, you can then cast to whatever you want.

这是不安全的,不建议这样做。但是,当你执行的操作非常困难或无法输入并且想要确保结果具有所需的类型时,它有时会很有用。

¥This is unsafe and not recommended. But it's sometimes useful when you are doing something with a value which is very difficult or impossible to type and want to make sure that the result has the desired type.

例如,以下用于克隆对象的函数。

¥For example, the following function for cloning an object.

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}

为此创建类型会很困难,因为我们正在基于另一个对象创建一个新对象。

¥It would be hard to create a type for this because we're creating a new object based on another object.

如果我们通过 any 进行强制转换,我们可以返回一个更有用的类型。

¥If we cast through any, we can return a type which is more useful.

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!

旧版转换语法

¥Legacy casting syntax

在版本 0.229 之前,要围绕 value 创建类型转换表达式,你需要在 Type 中添加冒号 :,并用括号 ( ) 括住表达式。

¥Before version 0.229, to create a type cast expression around a value, you would add a colon : with the Type and wrap the expression with parentheses ( ).

(value: Type)

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

¥Note: The parentheses are necessary to avoid ambiguity with other syntax.