有人可以解释“可选功能参数”和“可能类型”之间的区别,如Flow文档的on this page所述?
这些定义非常相似:
也许类型:“也许类型适用于值是可选的地方”
可选功能参数:“功能可以有可选参数,其中问号?在参数名称后面。”
我从语法角度理解这些差异。但是,听起来两者都会在您想要为函数定义可选参数的情况下使用。你会在哪里使用一个?
没有区别。但它们也是完全不同的东西。
我认为这里存在一些概念混淆。以下是可选参数的示例:
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没有一些称为“可选参数”的内在特征。什么流程提供了一种键入可选参数的方法,称为“可能的类型”。
所以说我想在上面输入我的功能。好吧,第一遍可能看起来像这样:
// 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
作为第二个参数传递。当我们不传递布尔值时,flow会抛出错误。我们的参数不再是可选的。我们可以从lower
中删除类型,但是然后flow会将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
,并且通过输入lower作为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
案例重叠,希望能够传入null
作为可选参数。
嗯,这很常见,流量为我们提供了这种情况的语法糖,称为“可能的类型”。如果你能够将我们的Q
类型重命名为?
,那么你基本上可能有类型。
function recase(str: string, lower: ?boolean): string {
if (lower) {
return str.toLowerCase();
}
return str.toUpperCase();
}