美文网首页
Flow联合类型(Union Types)

Flow联合类型(Union Types)

作者: vincent_z | 来源:发表于2018-01-25 22:13 被阅读0次

联合类型(Union Types)

输入的值可能是多种类型中的一种。

有时创建一组类型并以其中一个类型为准是很有用的。 例如,你可能希望编写一个接受一组原始值类型的函数。

// @flow
function toStringPrimitives(value: number | boolean | string) {
  return String(value);
}

toStringPrimitives(1);       // Works!
toStringPrimitives(true);    // Works!
toStringPrimitives('three'); // Works!

// $ExpectError
toStringPrimitives({ prop: 'val' }); // Error!
// $ExpectError
toStringPrimitives([1, 2, 3, 4, 5]); // Error!

联合类型语法

联合类型是通过竖线|连接的任意数量的类型。

Type1 | Type2 | ... | TypeN

或者

type Foo =
  | Type1
  | Type2
  | ...
  | TypeN

联合类型的每个成员可以是任何类型,甚至是另一个联合类型。

type Numbers = 1 | 2;
type Colors = 'red' | 'blue'
type Fish = Numbers | Colors;

传入与处理

当调用接受联合类型的函数时,我们必须传入其中的一种类型。但是在我们的函数里面,我们需要处理所有可能的类型。

// @flow
// $ExpectError
function toStringPrimitives(value: number | boolean | string): string { // Error!
  if (typeof value === 'number') {
    return String(value);
  } else if (typeof value === 'boolean') {
    return String(value);
  }
}

这里我们没有处理每一种情况(漏掉了string类型的处理),Flow抛出异常。

联合与改进

当你有一个联合类型的值时,把它分开并分别处理每个类型通常是有用的。使用Flow中的联合类型,可以将值精简为单个类型。上面的例子中我们可以使用JavaScript的typeof运算符分别处理数字大小写。

// @flow
function toStringPrimitives(value: number | boolean | string) {
  if (typeof value === 'number') {
    return value.toLocaleString([], { maximumSignificantDigits: 3 }); // Works!
  }
  // ...
}

不相交联合

例如,假设在发送请求后,我们有一个处理服务器响应的函数。当请求成功时,我们将返回一个成功的属性。

{ success: true, value: false };

当请求失败时,我们将返回一个失败的属性。

{ success: false, error: 'Bad request' };

我们可以尝试在单个对象类型中表示这两个对象。

// @flow
type Response = {
  success: boolean,
  value?: boolean,
  error?: string
};

function handleResponse(response: Response) {
  if (response.success) {
    // $ExpectError
    var value: boolean = response.value; // Error!
  } else {
    // $ExpectError
    var error: string = response.error; // Error!
  }
}

试图将这两种不同的类型合并成一个单一的类型并使用时,Flow会抛出异常。相反,如果我们创建了两种对象类型的联合类型,Flow将能够根据success属性知道我们正在使用哪个对象。

// @flow
type Success = { success: true, value: boolean };
type Failed  = { success: false, error: string };

type Response = Success | Failed;

function handleResponse(response: Response) {
  if (response.success) {
    var value: boolean = response.value; // Works!
  } else {
    var error: string = response.error; // Works!
  }
}

确切类型的不相交联合

不相交联合要求你通过单个属性区分不同对象。

// @flow
type Success = { success: true, value: boolean };
type Failed  = { error: true, message: string };

function handleResponse(response:  Success | Failed) {
  if (response.success) {
    // $ExpectError
    var value: boolean = response.value; // Error!
  }
}

这由于宽度子类型的缘故,Flow允许传递一个比预期的拥有更多属性的对象。

// @flow
type Success = { success: true, value: boolean };
type Failed  = { error: true, message: string };

function handleResponse(response:  Success | Failed) {
  // ...
}

handleResponse({
  success: true,
  error: true,
  value: true,
  message: 'hi'
});

除非对象彼此间差异,否则无法区分。所以,只有使用确切的对象类型才能解决问题。

// @flow
type Success = {| success: true, value: boolean |};
type Failed  = {| error: true, message: string |};

type Response = Success | Failed;

function handleResponse(response: Response) {
  if (response.success) {
    var value: boolean = response.value;
  } else {
    var message: string = response.message;
  }
}

有了确切的对象类型,我们不能添加额外的属性,所以对象彼此间差异,我们能够区分哪个是哪个。

相关文章

网友评论

      本文标题:Flow联合类型(Union Types)

      本文链接:https://www.haomeiwen.com/subject/oqvbaxtx.html