使用条件类型实现TypeScript中的函数重载

更新日期: 2021-10-26阅读: 1.2k标签: 重载

假设有这样的一个函数,你会怎么来声明他的类型呢?

function add(a,b){
    return a+b;
}

add函数可能有两种情况:

  1. 参数a、b为number类型,返回值为number类型
  2. 参数a、b为string类型,返回值为string类型

使用函数重载能解决吗?

首先,你可能会通过声明多个函数类型,来实现对add函数的重载声明。

function add(a: string, b: string): string;
function add(a: number, b: number): number;
function add(a: any, b: any) {
    return a + b;
}
add(1, 2); //function add(a: number, b: number): number
add('x', 'y'); //function add(a: string, b: string): string

这种方法显然不错,但是有一个小问题:当传入的参数类型是number|string时,会出现意想不到的类型错误。

let a:string|number;
add(a,a);
/*
  第 1 个重载(共 2 个),“(a: string, b: string): string”,出现以下错误。
    类型“string | number”的参数不能赋给类型“string”的参数。
      不能将类型“number”分配给类型“string”。
  第 2 个重载(共 2 个),“(a: number, b: number): number”,出现以下错误。
    类型“string | number”的参数不能赋给类型“number”的参数。
      不能将类型“string”分配给类型“number”。
*/

这是因为当我们使用函数重载时,TypeScript是使用这些重载来逐个比对的,直到匹配到合适的类型重载。但是显然,我们声明的两种重载中的变量类型,number和string都与number|string不匹配,所以出现了类型错误。

使用泛型怎么样呢?

然后,你还可能会想到使用泛型来声明类型,以便构建一种通用的模式。

function add<T extends number | string>(a: T, b: T): T;
function add(a: any, b: any) {
    return a + b;
}
const a:number = 0;
const b:string='str';
add(a, a);//function add<number>(a: number, b: number): number
add(b, b);//function add<string>(a: string, b: string): string

这个方法看起来也很好,但是同样有一个小问题:当传入字面量类型的参数时,该参数的类型会被认为和参数的值相同的类型。例如:

add(1,2);//function add<1 | 2>(a: 1 | 2, b: 1 | 2): 1 | 2

参数1的type是1,而number,就如同我们声明了 type T=1|2;一样,函数类型声明中的泛型T既要满足第一个参数1,又要满足第二个参数2,所以T的类型成为了1|2;同样的,如果传入的变量a、b没有显式的类型声明number和string,也会出现这个问题。

条件类型可能会更好

其实,在这种函数需要重载的时候使用条件类型,可能会有更好的效果。

function add<T extends number | string>(
    a: T,
    b: T
): T extends number ? number : string;
function add(a: any, b: any) {
    return a + b;
}
add(1,2);//function add<1 | 2>(a: 1 | 2, b: 1 | 2): number
let a:number|string;
add(a, a);//function add<string | number>(a: string | number, b: string | number): string | number

这种方式是先通过泛型的方法获取到参数的类型,在使用条件类型进行判断,从而得出正确的类型。

这种方法相较于前两种方法写起来更复杂,但是类型会更加准确。在函数需要类型重载时,不妨考虑一下使用条件类型来实现。

来自:https://segmentfault.com/a/1190000040861708

链接: https://fly63.com/article/detial/10762

通常面向对象语言的重载技术

通常面向对象语言的重载技术,其基本语法是这样的:在一个类中,有多个同名的方法,每个方法的参数不同而已。这种现象就称为“重载”

Js模拟函数重载

《JavaScript高级程序设计》中提及,JavaScript 不支持函数重载。若出现函数名称相同情况下,后者覆盖前者,故此不会出现重载的情况。 这项特性允许创建数项名称相同但输入输出类型或个数不同的子程序

js中实现函数重载

最近在js的学习中,看到了函数重载的问题,一开始,只看到了实现代码,看着代码冥思苦想了半个小时,总算是理清了其实现的原理,也为其实现的巧妙感到赞叹,也是在自己搞懂原理之后,去网络上搜索了下

javascript可以重载吗?

所谓重载,就是一组相同的函数名,有不同个数的参数,在使用时调用一个函数名,传入不同参数,根据你的参数个数,来决定使用不同的函数!但是我们知道js中是没有重载的,因为后定义的函数会覆盖前面的同名函数,但是我们又想实现函数重载该怎么办呢

js函数重载

重载,简单说,就是函数或者方法有相同的名称,但是参数列表不相同的情形,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法。参考javascript 高级程序设计(第三版)P66 ES函数不能够像传统意义上那样实现重载。而在其他语言中(如java)中

什么是 TypeScript 中的函数重载?

你知道为什么下图中定义了这么多ref函数,它们是干什么用的吗?如果你还不是很清楚,看完本文的内容,或许你就会明白了。这是一个简单的logError函数,接受一个字符串类型的参数,用于输出错误信息。

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!