我对此也感到非常困惑。来自一个Kotlin/Java 安卓背景知识,我不得不说 Typescript 的重载机器需要一段时间才能掌握。
首先我们需要解决如何声明overload
在打字稿中
问题 1:声明重载的方式不正确[不是问题的原因]
我关于处理重载的最初想法是编写以下代码:
function makeDate(timestamp: number): void { /* code */ }
function makeDate(m: number, d: number, y: number): void { /* code */ }
我立刻就被击中了Duplicate function implementation.ts(2393)
棉绒错误。一开始我很困惑,因为这就是你声明的方式overload
在 Java 和 Kotlin 中。然而,这实际上不是你声明的方式overload
在 Typescript 中,我相信这是问题的主要原因。
问题1的答复:
结果在 Typescript 中声明了overload
不是通过使用具有相同名称和不同签名的两个方法以及各自的实现来实现。相反,它首先定义具有相同名称和不同签名但没有主体的方法,最后提供一个具有实现的方法(方法主体),该方法能够处理所有先前声明的无主体方法。
问题 2:论证的数量不正确overload
要求[问题的原因]
现在我已经找到了在 Typescript 中创建重载方法的正确方法,我直接编写了以下代码:
[代码2.1]
function fn(x: string): void; // <-- Define one way to call method
function fn(x: string, y: string, z: string): void; // <-- Define another way to call method with more param (overloaded way)
function fn(x: string, y?: string, z?: string): void { // <--- provide a method with a body that can handle both previous two declarations
if (y === undefined) {
console.log("branch 1")
} else {
console.log(`branch 2 -> ${x} :: ${y} :: ${z}`)
}
}
fn("x")
fn("xxx", "yyy", "zzz")
Outputs:
$ branch 1
$ branch 2 -> xxx :: yyy :: zzz
在上面的代码片段中,我们声明了1 method with 2不同的过载。
- 过载 1 ->
function fn(x: string): void;
- 过载 2 ->
function fn(x: string, y: string, z: string): void;
它们都是由“具体的” method:
function fn(x: string, y?: string, z?: string): void {
if (y === undefined) {
console.log("branch 1")
} else {
console.log(`branch 2 -> ${x} :: ${y} :: ${z}`)
}
}
由于这个方法有一个主体,这就是为什么我称它为具体方法。另请注意,此方法处理这种情况@params: x
, 与@params: y and z
是可选的,通过这样做它涵盖了方法调用 {overload1
and overload2
}。这是一个有效的重载。
遵循同样的心态,我继续编写了以下代码:
[代码2.2]
function fn2(x: string): void;
function fn2(x: string, y: string): void;
function fn2(x: string, y?: string): void {
if (y === undefined) {
console.log("branch 1")
} else {
console.log(`branch 2 -> ${x} :: ${y}`)
}
}
fn2("x")
fn2("x", "y")
Outputs:
$ branch 1
$ branch 2 -> x :: y
该代码也有效,正如我所怀疑的那样。所以我又写了一些代码:
[代码2.3]
function fn3(): void;
function fn3(x?: string): void {
if (x === undefined) {
console.log("branch 1")
} else {
console.log(`branch 2 -> ${x}`)
}
}
fn3()
fn3("x")
但这一次代码不起作用并且tsc
正在抱怨:
Playground.ts:219:5 - error TS2554: Expected 0 arguments, but got 1.
219 fn3("x")
~~~
Found 1 error.
现在我们应该花一些时间来理解文档中的引用:
从外部看不到实现的签名。当编写重载函数时,您应该始终在函数的实现之上有两个或多个签名。
我下面的理解不正确。我在这里混合犯了错误args
and signature
。所以下面的文字是不正确的。把它留在这里作为一个坏例子。请参阅下面@David 的回答,因为他提供了一个很好的解释来说明为什么这是不正确的。例如:下面附加的代码片段也是具有 0 ~ 1 个参数的有效重载。这可以与产生语法错误的[代码2.3]进行比较。
function fn3(): void;
function fn3(x: string): void;
function fn3(x?: string): void {
if (x === undefined) {
console.log("branch 1")
} else {
console.log(`branch 2 -> ${x}`)
}
}
> calling:
fn3()
output:
> [LOG]: "branch 1" // correct behavior
如果你想得太多,这会很令人困惑,事实证明你可以简单地理解它“你必须有 2 个以上的参数才能进行重载”,这就是代码示例的原因[code 2.1]
and [code 2.2]
工作了。自从:
- For the
[code 2.1]
it had 1 and 3参数。符合上述文档的要求
- For
[code 2.2]
it had 1 and 2。这也符合文档中的要求。
- 然而,对于
[code 2.3]
it had 0 and 1。这不符合要求您应该始终在函数的实现上方有两个或多个签名在文档中,这就是为什么tsc
正在抱怨。
这实际上是有道理的,因为:
function fn3(): void;
function fn3(x?: string): void {
if (x === undefined) {
console.log("branch 1")
} else {
console.log(`branch 2 -> ${x}`)
}
}
与仅定义一个参数相同?
可选参数:
function fn3(x?: string): void {
if (x === undefined) {
console.log("branch 1")
} else {
console.log(`branch 2 -> ${x}`)
}
}
不正确:参见@David的回答
### 对问题 2 的回答:
重载方法声明仅适用于具有 2 个和 2 个以上参数的方法,并且需要具有主体的方法来处理您为重载声明的所有情况。此外,这不适用于具有0 to 1论据,tsc
会抱怨Expected 0 arguments, but got 1.ts(2554)
在这种情况下。同时,声明方法的重载0 and 1参数是多余的,因为您可以使用以下方法声明一个方法1可选参数。