方法重载(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. 前端BUG监控神器

    有时候,看到用户的反馈,我们往往会一脸茫然,因为反馈的信息太少了. 比如有用户反馈登录不了.为了解这个问题,一般的流程是这样的:首先试试自己能不能登录网站,发现没问题:然后查看后台日志,发现最近没有登 ...

  2. string_array.go

    package app import (     "strings" ) type StringArray []string func (a *StringArray) Set(s ...

  3. socketWriter.go

    package blog4go import ( "bytes" "fmt" "net" "sync" ) // Soc ...

  4. 【递推】Bzoj3612[Heoi2014]平衡

    Description 下课了,露露.花花和萱萱在课桌上用正三棱柱教具和尺子摆起了一个“跷跷板”.      这个“跷跷板”的结构是这样的:底部是一个侧面平行于地平面的正三棱柱教具, 上面 摆着一个尺 ...

  5. 【小白学C#】浅谈.NET中的IL代码

    一.前言 前几天群里有位水友提问:”C#中,当一个方法所传入的参数是一个静态字段的时候,程序是直接到静态字段拿数据还是从复制的函数栈中拿数据“.其实很明显,这和方法参数的传递方式有关,如果是引用传递的 ...

  6. linux清除全屏快捷键(Ctrl+L)

    Linux用户基本上都习惯使用clear命令或Ctrl+L组合快捷键来清空终端屏幕.这样做其实并没有真正地清空屏幕,但当用鼠标向上滚时,你仍然能看到之前的命令操作留下来的输出.

  7. python 模块之lxml 防xss攻击

    Use lxml.html.clean! It's VERY easy! from lxml.html.clean import clean_html print clean_html(html) S ...

  8. shell的嵌入命令大全

    围绕以下几点展开学习: 1.什么是shell的嵌入命令? 2.为什么使用shell? 3.怎样使用shell嵌入命令? 1.什么是shell的嵌入命令: ♦这些命令是在实际的Bourne shell里 ...

  9. 带logo图片或不带logo图片的二维码生成与解析,亲测成功

    最近公司需要实现二维码功能,本人经过一顿百度,终于实现了,因有3个功能:不带logo图片.带logo图片.解析二维码,篇幅较长,请耐心读之,直接复制粘贴即可. 前提:myeclipse10:jar包: ...

  10. ajax分页借鉴

    大家好这是我分页是用的代码希望大家可以相互交流ajax局部刷新 var pageindex = 1; var where = ""; var Pname = "" ...