面向对象特性中,最根本的就是面向对象的三大基本特征:封装、继承、多态。同时,TypeScript中也存在多态的使用,比如函数重载,今天我们先看一下函数重载以及泛型的概念。

什么是函数重载

简单来说,函数重载具有两个特征:名称相同,参数不同(参数类型、个数不同。)所以,函数重载的解释应该是具备不同参数的同名函数。注意:函数重载是多态的一种体现

函数重载的声明和实现

TypeScript中,函数重载主要包括两部分:函数声明,和函数实现。函数声明主要是TSC解析的一种声明体现,实际编译中,并不会编译成具体代码。我们可以通过TypeScript的playground来查看。

1、参数不同的函数重载

加入我们有一个打印函数,可以打印输入的一个string信息,我们可以将函数声明如下:

// 函数声明
function print(info: string): void;

  

而还有另一种情况,就是输入的有可能是两个string类型的参数,我们都需要打印下来,于是我们的函数声明可以是这样:

// 函数声明
function print(info: string, message: string): void;

  

而当这两种声明,同时存在TypeScript的声明文件中,我们就需要用函数重载来实现,这是JavaScript没有的特性。

而实现函数重载的要求就是,我们要在一个更为宽泛的范围去实现函数重载,所以,TypeScript中的我们实现print函数如下:

// 在更宽泛的范围,我们用可选参数来实现重载
function print(info: string, message ?: string) {
let printValue: string = info;
if(message){
printValue += message;
}
console.log(printValue);
}

  

2、参数个数相同,但类型不同的函数重载

函数重载的第二种情况,参数个数相同,但是参数类型不一样,这种情况下也可以通过重载来实现。

比如,上述打印信息的函数,有可能接受的输入是一个string字符串,也有可能输入接受的是一个number类型的数字,那么我们第一步的函数声明便是如下:

function print(info: string): void;
function print(num: number): void;

  

从上可以看到,我们的函数声明中,参数的类型是不同的,在这种情况下,TypeScript是如何在一个宽泛的范围内实现呢?这里就要用到联合类型,如下所示:

function print(message: string | number) {
console.log(message)
}

  

函数重载的总结

从我们实现两个函数重载的例子可以看出,我们在TypeScript中实现函数重载的方式分别是利用了TypeScript中的两个类型特性:可选类型以及联合类型。

所以,如果从便捷的角度来讲,我们如果是遇到了类似的实现,其实可以直接使用可选参数和联合类型来实现自己想要的函数效果。

泛型

在函数重载的不同参数类型,相同参数个数的重载中,我们介绍了它的重载实现方式,利用联合类型来实现,但是如果要打印出来的类型有很多,那么我们最终只能用any类型来实现print函数了。

但是,如果用any类型实现一个可以打印任意值的print函数,这样又让我们的函数变得类型缺失,这个时候,泛型这种解决方案也就应运而生。

什么是泛型

泛型指的是一种情况:定义是可以是任意类型,但是在编译的时候,必须有明确的类型。

有点绕,那么我们用泛型来实现上述第二个函数重载的例子,结合这个例子,可以体会一下这句话的含义。

function print<T>(message: T) {
console.log(message);
}

  

在这个函数中,泛型表示的方式是:函数名称<泛型参数>(arg: 泛型参数)。

这个函数在声明之后,函数类型是一个泛型。我们可以传递任意的类型参数到print函数中,但是当我们传递一个string类型的时候,这个函数便是一个string类型的函数了,已经在tsc编译阶段开始明确指定类型,这是和any函数所不一样的地方。

泛型的好处

首先,我们不用定义过多的联合类型来让函数变得复杂而又冗长,如:

function print(arg: string | number | boolean | array | 自定义类型) {
// 我们应该尽量避免多类型的传值函数,此时我们应该用泛型来实现。
}

  

其次,泛型可以是任何类型,但是在编译时一定是类型确定的。而且泛型也可以有继承属性,可以继承接口获取更多的类型定义等。

function print<T extends Interface> (arg: T) {
// 通过继承,来让泛型有更多的可变性。
}

  

最后,类型别名也可以是泛型,如我们可以做如下类型定义:

type Person<T> = { age: T }

  

泛型总结

总体来说,利用泛型,也是为了更准确的让我们使用类型思维,是为了更准确的描述参数、或者声明的类型准确性,如果能够熟练的掌握泛型,那么在TypeScript的开发中,将会有不一样的体验。

而常常以类型思维去思考JavaScript中的函数或者变量,我们也就会减少很多因为类型方面的犯错,使得我们的项目不仅更好的测试,也会更少的出错。

不得不说,在大前端领域,类型思维的缺失的确是个普遍现象,如果将类型思维捡起来,将会是一个可能存在着痛苦的过程,但是我相信,如果你做到了,那么你不仅会在开发代码的时候会更谨慎,能开发出更优秀的应用程序,还会体验到前端行业别样的魅力。

我的博客地址:http://www.gaoyunjiao.fun/?p=130

深入浅出TypeScript(3)- 函数重载和泛型的更多相关文章

  1. typescript 实现函数重载

    class Demo { // #region 声明 log() : void; log(arg1: string): void; log(arg1: number, arg2: string): v ...

  2. TypeScript 中函数的理解?与 JavaScript 函数的区别?

    一.是什么 函数是JavaScript 应用程序的基础,帮助我们实现抽象层.模拟类.信息隐藏和模块 在TypeScript 里,虽然已经支持类.命名空间和模块,但函数仍然是主要定义行为的方式,Type ...

  3. 函数的重载与 泛型(generic)有什么不同?

    函数重载指   重载函数,形参(类型)不同,实现的功能一样. 泛型算法指2个方面:这些算法可作用于各种不同的容器类型,而这些容器类型又可以容纳多种不同类型的元素.

  4. TypeScript Function(函数)

    在JavaScript中,函数是构成任何应用程序的基础块.通过函数,你得以实现建立抽象层.模仿类.信息隐藏和模块化.在TypeScript中,虽然已经存在类和模块化,但是函数依旧在如何去"处 ...

  5. C++学习笔记之模板(1)——从函数重载到函数模板

    一.函数重载 因为函数重载比较容易理解,并且非常有助于我们理解函数模板的意义,所以这里我们先来用一个经典的例子展示为什么要使用函数重载,这比读文字定义有效的多. 现在我们编写一个交换两个int变量值得 ...

  6. Typescript 学习笔记七:泛型

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  7. typescript - 3.函数

    (1)函数的定义 ## 函数声明法 // function run():string{ // return 'run'; // } //错误写法,返回类型错误 // function run():st ...

  8. 《前端之路》- TypeScript(二) 函数篇

    目录 一.定义函数方法 二.定义函数传参 三.可选传参 四.默认传参 五.传递剩余参数 六.函数重载 七.箭头函数 八.总结 一.定义函数方法 在 es5 中定时函数的方法有 命名函数和函数表达式(匿 ...

  9. 【C++】多态性(函数重载与虚函数)

    多态性就是同一符号或名字在不同情况下具有不同解释的现象.多态性有两种表现形式: 编译时多态性:同一对象收到相同的消息却产生不同的函数调用,一般通过函数重载来实现,在编译时就实现了绑定,属于静态绑定. ...

随机推荐

  1. VisualStudio中的单元测试

    1. VisualStuio中的测试资源管理器.CodeLens和ReSharper 上一篇文章重温了<单元测试的艺术>里提到的单元测试的技术及原则.这篇文章实践使用VisualStudi ...

  2. Java 获取操作系统相关的内容

    package com.hikvision.discsetup.util; import java.lang.reflect.Field; import java.net.InetAddress; i ...

  3. 【POJ - 2456】Aggressive cows(二分)

    Aggressive cows 直接上中文了 Descriptions 农夫 John 建造了一座很长的畜栏,它包括N (2 <= N <= 100,000)个隔间,这些小隔间依次编号为x ...

  4. Filebeat6.3文档—Log input配置

    Filebeat6.3文档-Log input配置 paths 日志加载的路径.例如加载某一子目录级别下面路径的日志:/var/log/*/*.log.这表示会去加载以.log结尾的/var/log下 ...

  5. DataOps系列丨数据的“资产负债表”与“现状”

    作者:DataPipeline CEO 陈诚 <跨越鸿沟>的作者Geoffrey Moore曾说“没有数据,运营企业就像一个又聋又瞎的人在高速上开车一样”.数据的价值从未像现在这样被企业重 ...

  6. Jquery事件和选择器 纠错

    1: 试题分析:该题考的是jQuery中事件绑定的知识.绑定事件用bind()方法,选项A是正确的绑定事件语法,因此是正确的答案.选项BCD的语法是错误的. 2: 试题分析:opacity 必需.规定 ...

  7. sqoop 密码别名模式 --password-alias

    sqoop要使用别名模式隐藏密码 1.首先使用命令创建别名 hadoop credential create xiaopengfei  -provider jceks://hdfs/user/pass ...

  8. 浅谈NodeJS多进程服务架构基本原理

    阅读目录 一:nodejs进程进化及多进程架构原理 二:node中child_process模块实现多进程 三:父子进程间如何通信? 四:理解cluster集群 回到顶部 一:nodejs进程进化及多 ...

  9. SpringBoot入门及YML文件详解

    SpringBoot 简介 微框架,与 Spring4 一起诞生,基于约定.生来为了简化 spring 的配置 优点 可以快速的上手,整合了一些子项目(开源框架或者第三方开源库) 可以依赖很少的配置快 ...

  10. 【Java例题】2.7找零钱

    7.为顾客找零钱时,希望选用的纸币张数最少. 例如73元,希望零钱的面值为五十元1张,二十元1张,一元3张. 设零钱面值有五十元.二十元.十元.五元和一元, 请编写程序,用户输入100以下的数, 计算 ...