方法重载(overload)在传统的静态类型语言中是很常见的。JavaScript 作为动态语言, 是没有重载这一说的。一是它的参数没有类型的区分,二是对参数个数也没有检查。虽然语言层面无法自动进行重载,但借助其动态的特性,我们可以在代码中手动检查入参的类型,或者通过 arguments 获取到参数个数,从而实现根据不同的入参做不同的操作。

比如有一个获取聊天消息的方法,根据传入的参数从数组中查找数据。如果入参为数字,则认为是 id,然后从数据源中找对应 id 的数据并返回,否则当成类型,返回这一类型的消息。

function getMessage(query) {
if (typeof query === "nunber") {
return data.find(message => message.id === query);
} else {
return data.filter(message => message.type === query);
}
}

TypeScript 中,假如我们的消息数据为如下结构:

type MessageType = "string" | "image" | "audio";

type Message = {

id: number;

type: MessageType;

content: string;

};

上面获取数据的方法等价于:

function getMessage(
query: number | MessageType
): Message[] | Message | undefined {
if (typeof query === "number") {
return data.find(message => message.id === query);
} else {
return data.filter(message => message.type === query);
}
}

这样做一是类型书写上比较丑陋,二是没有发挥出 TypeScript 类型检查的优势,这里我们是可以根据入参的类型明确知道返回的类型的,即如果传入的是 id,返回的是单个数据或undefined,如果是根据类型查找,返回的是数组。而现在调用方法后,得到的类型太过宽泛,这和使用 any 做为返回没多大差别。

函数返回类型不够紧凑

因为类型的不明朗,返回的结果都不能直接操作,需要进行类型转换后才能继续。

const result1 = getMessage("audio");
/** 不能直接对 result1 调用数组方法 */
console.log((result1 as Message[]).length); const result2 = getMessage(1);

if (result2) {

/** 不能对 result2 直接访问消息对象中的属性 */

console.log((result2 as Message).content);

}

重载的实现

这时候可通过提供多个函数类型的声明来解决上面的问题,最后得到的结果就是间接实现了函数的重载。当然这个重载只是 TypeScript 编译时的。

function getMessage(id: number): Message | undefined;
function getMessage(type: MessageType): Message[];
function getMessage(query: any): any {
if (typeof query === "number") {
return data.find(message => message.id === query);
} else {
return data.filter(message => message.type === query);
}
}

这样改造后,我们在调用的时候直接就会有重载的提示。

实现 TypeScript 的重载后调用时的自动提示

并且得到的结果类型是重载方法中指定的入参与返回的组合,在对结果进行使用时,无须再进行类型转换。

const result1 = getMessage("audio");
/** ✅ 无须类型转换 */
console.log(result1.length); const result2 = getMessage(1);

if (result2) {

/** ✅ 无须类型转换 */

console.log(result2.content);

}

这里需要理解的是,上面添加的函数类型仅作为 TypeScript 在编译时使用的,它不是真的实现像传统静态类型语言那样的重载,也不会改变编译后代码的输出。实际运行时仍然是不带重载的 JavaScript 版本。

编译后的代码
"use strict";
var data = [
{
id: 0,
type: "string",
content: "hello"
},
{
id: 1,
type: "image",
content: "url_for_iamge"
},
{
id: 2,
type: "string",
content: "world"
}
];
function getMessage(query) {
if (typeof query === "number") {
return data.find(function (message) { return message.id === query; });
}
else {
return data.filter(function (message) { return message.type === query; });
}
}
var result1 = getMessage("audio");
/** ✅ 无须类型转换 */
console.log(result1.length);
var result2 = getMessage(1);
if (result2) {
/** ✅ 无须类型转换 */
console.log(result2.content);
}

但这一点也不影响我们在 TypeScript 中使用这种假的重载。

可选参数

另一个 TypeScript 重载的场景。还是上面获取消息数据的方法,因为根据类型查找消息时,会返回同类型消息的一个数组。此时我们想加一个参数实现只返回结果中前几个数据,那么可以很方便地进行如下的改造:

function getMessage(id: number): Message | undefined;
+function getMessage(type: MessageType, count?: number): Message[];
+function getMessage(query: any, count = 10): any {
if (typeof query === "number") {
return data.find(message => message.id === query);
} else {
+ return data.filter(message => message.type === query).splice(0, count);
}
}

通过重载,这个新增的参数很容易实现只针对入参 MessageType 时,这样如果我们有如下的调用,会得到编译时的报错:

/** 												

TypeScript 中的方法重载的更多相关文章

  1. JavaScript中的方法重载

    对js有些了解的人都知道,在js中根本就不存在像C#中的那种方法重载,而有的只是方法的覆盖,当你在js中敲入两个或多个同名的方法的时候,不管方法(函数)的参数个数怎么个不同,这个方法名只能属于最后定义 ...

  2. paip.编程语言方法重载实现的原理及python,php,js中实现方法重载

    paip.编程语言方法重载实现的原理及python,php,js中实现方法重载 有些语言,在方法的重载上,形式上不支持函数重载,但可以通过模拟实现.. 主要原理:根据参数个数进行重载,或者使用默认值 ...

  3. dubbo中Hessian方法重载问题处理

    dubbo中Hessian方法重载,报出如下错误信息: 十一月 , :: 下午 org.apache.catalina.core.StandardWrapperValve invoke 严重: Ser ...

  4. java中的方法重载与重写以及方法修饰符

    1. 方法重载Overloading , 是在一个类中,有多个方法,这些方法的名字相同,但是具有不同的参数列表,和返回值 重载的时候,方法名要一样,但是参数类型和参数个数不一样,返回值类型可以相同,也 ...

  5. Java中的方法重载

    一.什么是方法重载? 方法重载就是两个或多个方法的方法名相同,但是方法的形参类型,数量,顺序不同. 上面提到的三点也就是一个方法的特征标,只要有一点不相同,则该方法就不相同,就可以实现重载. 在这里的 ...

  6. 如何区分Java中的方法重载和重写

    首先说的是重载: 方法的重载 * 在同一个类中,方法名相同,参数列表不同.与返回值类型无关. * 参数列表不同: * A:参数个数不同 * B:参数类型不同 * C:参数的顺序不同(不算重载 报错) ...

  7. java中的方法——重载yu重写(转)

    重载(Overloading) (1) 方法重载是让类以统一的方式处理不同类型数据的一种手段.多个同名函数同时存在,具有不同的参数个数/类型. 重载Overloading是一个类中多态性的一种表现. ...

  8. java中的方法重载(overload)

    什么时候方法重载:当两个方法的功能是相似的,可以考虑使用方法重载.若两个方法根本没有关系,无必要使用方法重载. 什么时候代码会发生方法重载:三个条件:1,在同一个类中.2,方法名相同.3,参数列表相同 ...

  9. 062、Java中的方法重载

    01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...

随机推荐

  1. 多线程动态规划算法求解TSP(Traveling Salesman Problem) 并附C语言实现例程

    TSP问题描述: 旅行商问题,即TSP问题(Travelling Salesman Problem)又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须 ...

  2. ConcurrentLinkedQueue简介

    ConcurrentLinkedQueue是一个基于链表的无界线程安全队列,非阻塞实现方式,先进先出,适合高并发的场景. 非阻塞的性能较好,采用CAS,避免加锁的时间,保证数据一致性. 采用" ...

  3. balancer.go

    package) , {         close(b.upc)     }     return nil } func getHost(ep string) string {     url, u ...

  4. 【NOI赛前训练】——专项测试1·网络流

    T1: 题目大意: 传送门 给一个长度为$n(n<=200)$的数列$h$,再给$m$个可以无限使用的操作,第$i$个操作为给长度为花费$c_i$的价值给长度为$l_i$的数列子序列+1或-1, ...

  5. RabbitMQ的介绍及使用进阶(Docker+.Net Core)

    目录: 一.什么是RabbitMQ 二.RabbitMQ运用场景 三.RabbitMQ优势及特点 四.Centos7中Docker安装RabbitMQ 五..Net Core 中使用RabbitMQ ...

  6. 史上最最靠谱,又双叒叒简单的基于MSXML的XML解析指南-C++

    目录 史上最最靠谱,又双叒叒简单的基于MSXML的XML解析指南 流程设计 xml信息有哪几种读取形式(xml文件或wchar) 如何选取节点,and取节点属性有哪些方法? IXMLDOMNode与I ...

  7. PHP 技能精进之 PHP-FPM 多进程模型

    PHP-FPM 提供了更好的 PHP 进程管理方式,可以有效控制内存和进程.可以平滑重载PHP配置.那么当我们谈论 PHP-FPM 多进程模型的时候,作为 PHPer 的你了解多少呢? 首先,让我们一 ...

  8. List-LinkedList、set集合基础增强底层源码分析

    List-LinkedList 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 继上一章继续讲解,上章内容: List-ArreyLlist集合基础增强底层源码分析:https:// ...

  9. 使用docker-compose 一键部署你的分布式调用链跟踪框架skywalking

    一旦你的程序docker化之后,你会遇到各种问题,比如原来采用的本地记日志的方式就不再方便了,虽然你可以挂载到宿主机,但你使用 --scale 的话,会导致 记录日志异常,所以最好的方式还是要做日志中 ...

  10. Docker最全教程之Python爬网实战(二十一)

    Python目前是流行度增长最快的主流编程语言,也是第二大最受开发者喜爱的语言(参考Stack Overflow 2019开发者调查报告发布).笔者建议.NET.Java开发人员可以将Python发展 ...