有人可以解释一下Flow文档on this page上的“可选功能参数”和“也许类型”之间的区别吗?
这些定义听起来非常相似:
可能的类型:“也许类型适用于值是可选的地方”
可选功能参数:“功能可以具有可选参数,其中参数名称后带有问号?。”
我从语法角度了解差异。但是,这听起来好像都想在要为功能定义可选参数的情况下使用。您将在哪里使用另一个?
答案 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
可以是boolean
或undefined
(未指定为参数)。
显然,这是一个非常常见的情况。实际上如此普遍,以至于我们可能会考虑封装它。这可以通过泛型来完成,例如:
// 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
,那么您基本上可以拥有类型。
?