流类型:“可选功能参数”和“可能的类型”之间的差异

时间:2019-02-27 23:29:21

标签: javascript types flowtype flow-typed

有人可以解释一下Flow文档on this page上的“可选功能参数”和“也许类型”之间的区别吗?

这些定义听起来非常相似:

可能的类型:“也许类型适用于值是可选的地方”

可选功能参数:“功能可以具有可选参数,其中参数名称后带有问号?。”

我从语法角度了解差异。但是,这听起来好像都想在要为功能定义可选参数的情况下使用。您将在哪里使用另一个?

1 个答案:

答案 0 :(得分:2)

没有区别。但它们又是完全不同的东西。

我认为这里存在一些概念上的混乱。这是一个可选参数的示例:

function recase(str, lower) {
  if (lower) {
    return str.toLowerCase();
  }

  return str.toUpperCase();
}

recase('Test', true)
// "test"
recase('test')
// "TEST"
recase()
// Uncaught TypeError: Cannot read property 'toUpperCase' of undefined

我们的函数有两个参数。第一个是必需的,如果我们不传递至少一个参数,则该函数将引发异常。第二个是可选的,如果我们不通过第二个,则不会抛出异常,返回的值将有所不同。

请注意,我没有介绍任何类型。这是因为此处的“可选参数”只是一般的编程概念。 Flow没有称为“可选参数”的某些固有功能。流程提供的是一种 type 可选参数的方法,称为“也许类型”。

所以说我想在上面输入我的函数。好吧,第一遍可能看起来像这样:

// We're taking a string and a boolean and returning a string, right?
function recase(str: string, lower: boolean): string {
  if (lower) {
    return str.toLowerCase();
  }

  return str.toUpperCase();
}

recase('Test', false)
// "TEST"
recase('Test', true)
// "test"
recase('Test')
// ^ Cannot call `recase` because function [1] requires another argument.

由于我们将lower键入为boolean,因此流程期望将boolean作为第二个参数传递。当我们不传递布尔值时,流程将引发错误。我们的参数不再是可选的。我们可以从lower中删除该类型,但流程会将lower默认为any类型,这意味着用户可以传递他们想要的任何东西,这使得我们类型不明确且容易出错。这是我们可以做的一件事:

function recase(str: string, lower: void | boolean): string {
  if (lower) {
    return str.toLowerCase();
  }

  return str.toUpperCase();
}

recase('Test', true)
// "test"
recase('Test')
// "TEST"

在流程中,void类型仅与值undefined相匹配。如果我们在调用lower时未提供recase的值,那么lower的值将为undefined,并通过键入较低的void | boolean告诉流程lower可以是booleanundefined(未指定为参数)。

显然,这是一个非常常见的情况。实际上如此普遍,以至于我们可能会考虑封装它。这可以通过泛型来完成,例如:

// Let's call this Q for "Question" but it's nice and short
type Q<T> = void | null | T;

function recase(str: string, lower: Q<boolean>): string {
  if (lower) {
    return str.toLowerCase();
  }

  return str.toUpperCase();
}

请注意,我们已经在通用类型中添加了null,因为undefined的情况与希望传递null的{​​{1}}情况有很多重叠可选参数。

嗯,这是如此普遍,以至于流程为我们提供了相当于这种情况的语法糖,称为“也许类型”。如果您能够将我们的null类型重命名为Q,那么您基本上可以拥有类型。

?