首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >重载签名和typescript中的实现签名

重载签名和typescript中的实现签名
EN

Stack Overflow用户
提问于 2021-07-02 00:38:37
回答 1查看 173关注 0票数 2

我正在阅读Typescript手册,我很难理解为什么下面的代码片段有错误消息:

代码语言:javascript
运行
复制
function fn(x: string): void;
function fn(vo) {
  // ...
}
// Expected to be able to call with zero arguments
fn();

这是解释,但我不明白,谁能给我解释一下这是怎么回事?

从外部看不到实现的签名。在编写重载函数时,应该始终在该函数的实现之上具有两个或更多签名。

EN

回答 1

Stack Overflow用户

发布于 2021-07-10 10:30:58

我也对此感到非常困惑。来自Kotlin/Java Android的背景,我不得不说,Typescript的重载机器需要一段时间才能掌握。

首先,我们需要解决如何在Typescript中声明overload

关注点1:声明重载的不正确方式不是问题的原因

关于处理重载,我最初的想法是编写以下代码:

代码语言:javascript
运行
复制
function makeDate(timestamp: number): void { /* code */ }
function makeDate(m: number, d: number, y: number): void { /* code */ }

我马上就被Duplicate function implementation.ts(2393)的lint错误击中了。一开始我很困惑,因为这是你在Java和Kotlin中声明overload的方式。然而,这实际上不是你在Typescript中声明overload的方式,我相信这是问题的主要原因。

对问题1的回答:

事实证明,在Typescript中,overload的声明不是通过拥有两个具有相同名称和不同签名的方法来实现各自的实现。相反,它首先定义具有相同名称和不同签名的方法,而不是主体,最后提供一个具有实现的方法(方法主体),该方法能够处理所有先前声明的无体方法。

关注点2:overload要求的参数数量不正确是问题的原因

现在我已经找出了在Typescript中创建重载方法的正确方法,我直接编写了以下代码:

代码2.1

代码语言:javascript
运行
复制
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")

输出:

代码语言:javascript
运行
复制
$ branch 1
$ branch 2 -> xxx :: yyy :: zzz

在上面的代码片段中,我们声明了带有2不同重载的1方法

具体的function fn(x: string): void;

  • overload重载1
  1. 2 -> function fn(x: string, y: string, z: string): void;,它们都是由具体的方法处理的:

代码语言:javascript
运行
复制
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是可选的,通过这样做,它涵盖了方法调用{overload1overload2}。这是一个有效的重载。

遵循同样的思路,我接着写了下面的代码:

代码2.2

代码语言:javascript
运行
复制
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")

输出:

代码语言:javascript
运行
复制
$ branch 1
$ branch 2 -> x :: y

代码也可以工作,就像我所怀疑的那样。所以我又写了一些代码:

代码2.3

代码语言:javascript
运行
复制
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抱怨道:

代码语言:javascript
运行
复制
Playground.ts:219:5 - error TS2554: Expected 0 arguments, but got 1.

219 fn3("x")
        ~~~

Found 1 error.

现在,我们应该花一些时间来理解文档中的引用:

从外部看不到实现的签名。在编写重载函数时,应该始终在该函数的实现之上具有两个或更多签名。

如果你想太多了,这是非常令人困惑的,事实证明你可以简单地理解为“你必须有2+参数才能做重载”,这就是为什么代码样例[code 2.1][code 2.2]有效。因为:

  • [code 2.1]它有13参数。这符合documentation
  • For [code 2.2]的要求,它有12。这也符合[code 2.3]的docs.
  • However,要求,它具有和1。这不符合这样的要求,即在文档中函数的实现之上应该始终有两个或更多的签名,这就是为什么tsc是complaining.

的原因

这实际上是有意义的,因为:

代码语言:javascript
运行
复制
function fn3(): void;
function fn3(x?: string): void {
    if (x === undefined) {
        console.log("branch 1")
    } else {
        console.log(`branch 2 -> ${x}`)
    }
}

与仅使用?可选参数定义一个参数相同:

代码语言:javascript
运行
复制
function fn3(x?: string): void {
    if (x === undefined) {
        console.log("branch 1")
    } else {
        console.log(`branch 2 -> ${x}`)
    }
}

所以,对问题2的回答是:

重载方法声明只适用于具有2和2+参数的方法,并且需要一个具有主体的方法来处理您为重载声明的所有情况。此外,这不适用于具有 to 1参数的方法,在这种情况下,tsc将抱怨Expected 0 arguments, but got 1.ts(2554)。同时,为带有和1参数的方法声明重载是多余的,因为您可以只使用1可选参数声明一个方法。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68213949

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档