关于typescript:TS-函数重载你还不会来我教你

8次阅读

共计 2590 个字符,预计需要花费 7 分钟才能阅读完成。

前言: 明天在我的项目中遇到了后端 接口参数类型 接口返回值 须要批改的场景,因为这个函数在很多页面都用到了,就导致改完相干 api 函数的时候 TS 疯狂报错,所有的参数和返回值都须要跟着改,一时间头疼。正当我不知所措的时候,忽然想到之前看 vue 源码的时候看到 函数重载 的应用,于是我第一次在我的项目中应用了 函数重载,完满解决了我的问题。


一. 场景再现

  1. 咱们先不要想函数重载是什么意思,咱们从具体场景一步一步去理解这个名词的含意,你会了解的更粗浅。
  2. 假如当初后端有一个接口,能够通过一个 ID 来获取用户信息。那么前端对应的 api 可能就有这样一个函数,
  3. 当初还有一个接口,就是通过很多个 ID 来获取很多个用户的信息。那么这个函数就可能被设计成这样子。
  4. 等等,先别着急喷。别说是你,我本人看着都感觉这种形式很蠢,为什么不把它设计成一个函数呢?哎,对哈,那咱们就入手革新一下这两个函数。
  5. 既然参数类型不同,那么后端对应的返回值类型必定也是不一样滴,咱们还须要设定一下返回值类型。咱们顺手定一个一个 interface 来示意这个后端接口返回给咱们的数据类型。

    所以当初咱们的函数就变成了上面这个样子。

  6. 这时候就须要前端手动去判断传递的参数到底是单个字符串还是一个字符串数组。
  7. 乍一看感觉还挺好,然而你会发现当你在调用这个函数的时候,TS 的类型提醒如同不是那么对劲。什么意思呢?咱们间接调用这个函数看一下类型晋升当初是什么样子的。

    你可能会说,你骗谁呢?这类型提醒不是好好的吗?别着急,容咱们再申明一个变量筹备接管这个函数的返回值。

  8. 当初我在一个组件外部很明确的晓得我要发送一个 ID 数组 去获取很多用户的数据。那么我能够很分明的定义咱们的变量就是 DataType[] 的类型。

    这里须要特地揭示:尽管当初我只产生了一个用户的数据,然而后端依据我的参数类型是一个数组,仍会返回一个数组类型的用户数据给我,即便那个数组只有一条用户数据。)

  9. 那么咱们就能够很天然的写出上面的代码。

    随之你就会发现 TS 飘红了,你函数的返回值类型和变量定义时候规定的类型不合乎。

  10. 谬误起因很简略,就是咱们人类的直觉 。咱们很聪慧的认为,我给你传递的如果是一个字符串,那么你这个函数就应该很听话的给我返回 个用户信息就完事了。我给你这个函数如果传递的是一个字符串数组,那么我就是我想获取 多个 用户的信息,你就应该给我返回一个信息数组。然而很道歉 TS 没有这么智能,它的确不晓得你到底是想一个 一个字符串 返回 ==> 一个数据 ,还是 一个字符串 返回 ==> 多个数据

    是的,TS 目前只晓得你的参数只有两个类型,你的返回值只有两个类型,然而它不晓得你的参数对应的你想返回哪个类型。

二. 解决飘红的办法

  1. 那么咱们如何解决目前 TS 飘红的问题呢?
  2. 第一种办法也是最简略的办法,间接应用 TS 类型断言 as 关键词,明确的通知 TS 你这个函数的返回值是什么。

    as 的作用你能够类比于 CSS 中的 important,我十分确定这个变量的类型是什么,不须要 TS 帮我做类型推导。

  3. 这也是我最开始应用的办法,也是我最常常应用的办法。你可能也看进去了,这样的话我就须要在每一个应用这个函数的中央都 as 一下,十分十分笨也不优雅。
  4. 那有没有什么办法让 TS 变聪慧一点,让它帮我主动分辨我各个参数对应什么返回值呢?你别说,还真有,引出咱们的配角 —-函数重载

三. 什么是函数重载(overload)

  1. 在引出 函数重载 之前咱们须要理解一个前提常识,在 JS 里同一个函数是能够被申明屡次的,后果是会优先采纳最初一次的函数体。什么意思呢?如下图,这是一个 .js 文件,JS 不仅不会报错,并且还能够失常执行。
  2. 然而在 TS 里这种形式是会引发类型报错的。尽管 TS 只是会揭示类型谬误,不影响这个文件的最终运行。然而明眼人都能够看出哪种开发模式更加适宜团队单干。很显著 TS 更加合乎咱们的直觉,不容许变量在同一作用域下屡次赋值。
  3. 所以 JS 是没有重载签名这个概念的,这是 TS 所给你带来的劣势。对于函数重载更加粗浅的实现原理,因为应用的不多我临时无奈给你深刻解说原理,在这里我仅谈一谈目前我集体了解,可能有些大白话,然而应该能够帮你先浅浅的理解这个名词。

    函数重载的概念次要由两局部组成。1. 重载签名 2. 实现签名

四. 重载签名

  1. 咱们先说重载签名,咱们晓得函数基本上是由四局部组成:一个函数名,一个函数参数,一个函数体,一个返回值。
  2. TS 能够帮你别离束缚 参数类型 返回值类型,也就是上面这两个。
  3. 重载签名 的意思就是只须要你提供一个函数的 参数类型 返回值类型,不须要你提供函数体。什么意思呢?这里咱们还拿刚刚获取用户信息 getData 举例子。
  4. 咱们就能够申明一个同名函数。getData 依照下面刚刚讲到的,咱们只束缚它的 参数类型 返回值类型。咱们发现,TS 居然没有报错。
  5. 依照同样的思路,咱们再申明一个通过 ID 数组 获取多个用户信息的函数。
  6. 如果你留心的话,到当初咱们其实曾经实现了函数重载。你会发现咱们当初曾经不须要 as 去通知 TS 类型了,它曾经帮咱们实现了推导。
  7. 咱们换一下参数类型,咱们把参数类型换成一个字符串看看是什么后果。你会发现,TS 十分聪慧的推断出,你想要的后果是一个用户的数据,并不是多个用户的数据,所以提醒你参数谬误。
  8. 咱们改一下 userData 的类型来确认一下咱们的猜测是否正确。

    TS 没有报错,果然是咱们所想的那样。

五. 实现签名

  1. 聪慧的你可能曾经猜到了,实现后面其实就是一个带有函数体的同名函数。并且这个函数的 参数类型 要齐全蕴含 函数签名 所有类型
  2. 什么意思呢?咱们删除了 string 数组 的参数类型。你会发现第二个函数签名飘红报错了。

    错误信息如下:

  3. 实现签名的返回值同理,不再过多赘述。
  4. 最重要的一点来了,你须要在实现签名内十分明确的判断出不同类型的参数所对应的返回值。能力让 TS 去实现准确的类型推导。
  5. 至此你曾经实现了题目的性能 —- 函数重载

六. 额定常识

  1. 函数重载能够有多个重载签名,然而只容许有一个实现签名。说白了就是一个函数名只能有一个函数体。
  2. 函数重载不仅仅只能束缚参数类型,还能依据参数的数量去返回不同的类型的返回值。(arguments:别忘了函数内还有我这个对象。T.T)
  3. Class 类也能够实现 constructor 的重载。
  4. 兴许你早就遇到过 TS 给你抛出的这个谬误,然而你之前可能不晓得是什么引起的。心里默念(overload+1)到底是什么鬼啊!

结语

TS 真是越用越香!!!🎁

正文完
 0