流类型:"optional function parameters" 和 "maybe types" 之间的差异

Flow Type: difference between "optional function parameters" and "maybe types"

有人可以解释一下 "optional function parameters" 和 "maybe types" 之间的区别吗?

定义听起来很相似:

可能类型: "Maybe types are for places where a value is optional"

可选函数参数: "Functions can have optional parameters where a question mark ? comes after the parameter name."

我从语法的角度理解差异。但是,听起来两者都可以用于您想要为函数定义 可选参数 的情况。你会在哪里使用一个而不是另一个?

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

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

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

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

请注意,我没有介绍任何类型。这是因为这里的 "optional parameter" 只是一个通用的编程概念。 Flow 没有一些称为 "optional parameters." 的内在特性,Flow 提供的是一种 type 可选参数的方法,称为 "maybe types."

假设我想在上面输入我的函数。嗯,第一遍可能是这样的:

// 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,flow 期望将 boolean 作为第二个参数传递。当我们不传递布尔值时,流程会抛出错误。我们的参数不再是可选的。我们可以 lower 中删除 类型,但是 flow 将默认 lowerany 类型,这意味着用户可以传递他们想要的任何内容这使得我们的类型模棱两可且容易出错。这是我们可以做的一件事:

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 的值。如果我们在调用 recase 时没有为 lower 提供值,那么 lower 的值将是 undefined,通过键入 lower as 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 情况与希望能够传入 [=31] 的 null 情况重叠太多=] 可选参数。

好吧,这很常见,以至于流为我们提供了相当于这种情况的语法糖,称为 "maybe types." 如果您能够将我们的 Q 类型重命名为 ?那么你基本上可能会有类型。

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

  return str.toUpperCase();
}