如何强制Flow将值转换为另一种类型?

cze*_*rny 28 casting flowtype

是否有可能在Flow中强制转换变量?

type StringOrNumber = string | number
const foo: StringOrNumber = 'hello'

// I look for something like `const bar:string = (string) foo`
const bar: string = foo // fails
const bar: string = (foo: string) // also fails
Run Code Online (Sandbox Code Playgroud)

log*_*yth 40

Flow不会直接从一种类型转换为另一种类型,但你可以做类似的事情

const bar: string = (foo: any);
Run Code Online (Sandbox Code Playgroud)

所以你foo转换为any,因为any接受任何类型的值作为输入.然后因为该any类型还允许您从中读取所有可能的类型,您可以将any值赋值为,bar因为a any也是a string.


小智 18

在示例中,您将看到从联合类型到其成员之一的"强制转换".虽然将此视为演员是常见的,但它与其他语言中的类型转换不同.

通过设置footo 的类型string | number,我们告诉Flow,这个值可以是字符串或数字.然后我们碰巧在其中放入了一个字符串,但Flow并没有放弃我们对它的类型的直接断言,因为即使在这种情况下(比如这个)以后它也无法改变.

要将它分配给一个string-typed变量,Flow需要知道即使它可能是一个string或者number,当我们进行赋值时,我们确信它只能是一个string.

减少可能选项的过程称为类型细化.

键入细化

为了改进类型,我们需要证明它必须是我们所说的类型,以Flow理解的方式.

在原始示例中,您可以使用typeof以下命令执行此操作:

type StringOrNumber = string | number
const foo: StringOrNumber = 'hello'

// This would raise an error here:
// const bar: string = foo

if (typeof foo === "string") {
  // Flow now knows that foo must be a string, and allows this.
  const bar: string = foo
}
Run Code Online (Sandbox Code Playgroud)

Flow并不理解人类可以看到的所有类型细化,因此有时您需要查看细化文档以查看可能使Flow理解的内容.

抑制评论

有时候没有办法表达Flow的改进的安全性.我们可以通过使用抑制注释来强制Flow接受语句,这将抑制Flow否则将报告的错误.默认抑制注释是$FlowFixMe,但可以配置为不同的注释或注释.

Flow将在第二行报告错误,报告unionValue可能是'number'类型:

const unionValue: StringOrNumber = 'seven'
const stringValue: string = unionValue
Run Code Online (Sandbox Code Playgroud)

但是,通过使用抑制注释,这会传递Flow:

const unionValue: StringOrNumber = 'seven'
// $FlowFixMe: We can plainly see this is a string!
const stringValue: string = unionValue
Run Code Online (Sandbox Code Playgroud)

抑制注释的一个有用特性是抑制注释没有跟随错误被抑制被认为是错误.如果我们更改示例中的类型:

const unionValue: string = 'seven'
// $FlowFixMe: Even though this is a string, suppress it
const stringValue: string = unionValue
Run Code Online (Sandbox Code Playgroud)

现在Flow将报告"未使用的抑制"错误,提醒我们.当Flow应该能够识别细化但不能通过使用抑制注释时,如果Flow的未来版本将代码识别为已删除注释(并获得额外的类型安全性),则此功能特别有用类型安全.

铸通任何

如果你真的不能在演示其安全流动的方式表达出来,而你不能(或不愿)使用抑制评论,你可以将任何类型anyany任何类型:

const unionValue: StringOrNumber = 'seven'
// Flow will be okay with this:
const stringValue: string = (unionValue: any)
Run Code Online (Sandbox Code Playgroud)

通过输出一个值,any我们要求Flow忘记它所知道的值的类型,并假设我们正在做的事情必须是正确的.如果我们稍后将它放入一个类型变量,Flow将认为必须是正确的.

注意事项

重要的是要注意抑制注释和强制转换都是不安全的.它们完全覆盖了Flow,并且很乐意执行完全无意义的"强制转换":

const notAString: {key: string, key2: number} = {key: 'value', key2: 123}
// This isn't right, but Flow won't complain:
const stringValue: string = (notAString: any)
Run Code Online (Sandbox Code Playgroud)

在这个例子中,stringValue持有objectfrom notAString,但Flow确定它是一个字符串.

为避免这种情况,请尽可能使用Flow理解的优化,并避免使用其他不安全的"投射"技术.