我正在尝试了解 Typescript 中的函数重载如何工作,但我不明白。检查此代码片段 ( ts Playground )(仅使用一个声明以使其尽可能简单):
function foo(x: number): 42
function foo(x: number) {
return x
}
const y = foo(23)
Run Code Online (Sandbox Code Playgroud)
有两件事不对劲:
y的推断值为42相反,如果我只是在函数实现上声明返回类型,则事情会按预期工作(或失败!):
function foo(x: number): 42 {
return x // -> Type 'number' is not assignable to type '42'.(2322)
}
const y = foo(4)
Run Code Online (Sandbox Code Playgroud)
让我们解决第一个问题:
\n\n\n即使实际返回类型明显与重载签名不匹配,函数声明也不会出现 TS 错误
\n
如果你看一下这个文档(此后已弃用,但我想它仍然有效),他们说:
\n\n\n为了让编译器选择正确的类型检查,它遵循与底层 JavaScript 类似的过程。它查看重载列表,并继续进行第一个重载,尝试使用提供的参数调用该函数。如果找到匹配项,它就会选择该重载作为正确的重载。因此,习惯上按从最具体到最不具体的顺序对重载进行排序。
\n
我的猜测是,当您编写实现时,它是相同的,对于您声明的每个重载,它将尝试用它来调用您的函数。我不知道这是否有道理。让我们看一个例子:
\nfunction foo(x: number): 42 // ok since 42 is compatible with number (number is wider than 42)\n\nfunction foo(x: number) {\n return x\n}\n\nconst y = foo(23)\nRun Code Online (Sandbox Code Playgroud)\n如果您获取签名,并尝试用它调用您的函数,那么它是“兼容的”。x 是一个数字,42 也是一个数字,我们实现的返回类型表明 x 是一个数字。
\n如果我这样做:
\nfunction foo(x: number): 42 // error: not compatible since 42 is not compatible with 32\n\nfunction foo(x: number) {\n return 32\n}\nRun Code Online (Sandbox Code Playgroud)\n我收到一个错误。另一条道路:
\nfunction foo(x: number): \'text1\'\nfunction foo(x: string): \'text2\'\n\nfunction foo(x: number | string) {\n return x // why is there no error?\n}\n\n//y is "text1" (no, it\'s a number!!!)\nconst y = foo(42)\n\n\n//there is no error because if you take the signature, you can call your function with it -> x is a number so compatible with number | string and \'text1\' is compatible with number | string\nRun Code Online (Sandbox Code Playgroud)\n那么你可能会问为什么会这样呢?如果按照下面的方式来看的话,就更容易推理了。
\n不是
\n\n\n我可以用我的函数实现来调用我的签名吗?
\n
相反
\n\n\n如果我采用我的签名之一,我可以用它调用我的函数实现吗?
\n
不要将重载视为函数实现必须满足的某种要求。您是否注意到错误出在重载上而不是函数实现上?这是必须与函数实现兼容的重载。
\n第二点:
\n\n\ny 的推断值为 42
\n
如果将鼠标悬停在函数实现上,您将看到它只显示重载。
\n该文档的最新版本说:
\n\n\n实现的签名从外部是不可见的。\n编写重载函数时,应该始终在函数的实现上方有两个或\n更多签名。
\n
它们提供了人们常犯的一个错误:
\nfunction fn(x: string): void;\nfunction fn() {\n // ...\n}\n// Expected to be able to call with zero arguments\nfn();\nExpected 1 arguments, but got 0.\nRun Code Online (Sandbox Code Playgroud)\n实现本身不算是重载。
\n所以调用函数时只能看到重载:
\nconst y = foo(23)\nRun Code Online (Sandbox Code Playgroud)\n因此,考虑到这一点,明智地使用它们的重载。剩下的就是你的责任了。顺便说一句,在您的用例中,您根本不需要使用重载。仅当您至少拥有其中两个时才应使用它。
\n| 归档时间: |
|
| 查看次数: |
444 次 |
| 最近记录: |