TypeScript 使用 Tuple Union 声明函数重载


Posted in Javascript onApril 07, 2022

问题:

TypeScript 中为函数添加多个签名后,依然需要添加相应的代码来判断并从不同的签名参数列表中获取对应的参数。过去常见的写法:

function refEventEmitter(event?: string): void;
function refEventEmitter(event: string, callback: () => void): void;
function refEventEmitter(callback: () => void): void;
function refEventEmitter(
  eventOrCallback?: string | (() => void),
  callback?: () => void,
): void {
  let event: string | undefined;

  if (typeof eventOrCallback === 'function') {
    callback = eventOrCallback;
  } else {
    event = eventOrCallback;
  }

  // ...
}

这个过程因为将原有参数列表直接按序号拍平,参数之间的类型关联需要人肉确保正确。

技巧:

这时我们可以通过使用tuple union 的参数类型,来无脑处理各种函数重载情况:

function refEventEmitter(event?: string): void;
function refEventEmitter(event: string, callback: () => void): void;
function refEventEmitter(callback: () => void): void;
function refEventEmitter(
  ...args:
    | [event?: string]
    | [
        event: string,
        callback: () => unknown,
      ]
    | [callback: () => unknown]
): void {
  let [event, callback] =
    args.length === 2
      ? args
      : typeof args[0] === 'function'
      ? [undefined, args[0]]
      : [args[0], undefined];

  // ...
}

实际上,此时上方的签名列表也不再需要了:

function refEventEmitter(
  ...args:
    | [event?: string]
    | [
        event: string,
        callback: () => unknown,
      ]
    | [callback: () => unknown]
): void {
  let [event, callback] =
    args.length === 2
      ? args
      : typeof args[0] === 'function'
      ? [undefined, args[0]]
      : [args[0], undefined];

  // ...
}
这篇其实拖了有点久,在写的时候发现 TypeScript 已经内置了 "Convert overload list to single signature" 的重构选项,可以一键将重载列表变为参数 tuple union。

不过到这里其实还存在问题,TypeScript 中 typeof 条件判断不能对整个对象进行收窄,只能收窄被 typeof 到的某个元素、属性。上面的例子中,如果需要的不只是 args[0] 就会出现问题。

此时我们可以引入一个工具函数 isTypeOfProperty(object, key, type)

此时实现就变成了:

function refEventEmitter(
  ...args:
    | [event?: string]
    | [
        event: string,
        callback: () => unknown,
      ]
    | [callback: () => unknown]
): void {
  let [event, callback] =
    args.length === 2
      ? args
      : isTypeOfProperty(args, 0, 'function')
      ? [undefined, args[0]]
      : [args[0], undefined];

  // ...
}

到此这篇关于TypeScript 使用 Tuple Union 声明函数重载的文章就介绍到这了,更多相关TypeScript 声明函数重载内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
javascript 复杂的嵌套环境中输出单引号和双引号
May 26 Javascript
分享XmlHttpRequest调用Webservice的一点心得
Jul 20 Javascript
JavaScript使用focus()设置焦点失败的解决方法
Sep 03 Javascript
javascript正则表达式总结
Feb 29 Javascript
Web前端开发工具——bower依赖包管理工具
Mar 29 Javascript
JS检测数组类型的方法小结
Mar 14 Javascript
JavaScript的六种继承方式(推荐)
Jun 26 Javascript
JavaScript函数节流和函数去抖知识点学习
Jul 31 Javascript
原生js基于canvas实现一个简单的前端截图工具代码实例
Sep 10 Javascript
js prototype深入理解及应用实例分析
Nov 25 Javascript
微信小程序wxml列表渲染原理解析
Nov 27 Javascript
js生成1到100的随机数最简单的实现方法
Feb 07 Javascript
Axios代理配置及封装响应拦截处理方式
vue-cil之axios的二次封装与proxy反向代理使用说明
Apr 07 #Vue.js
动态规划之使用备忘录来改进Javascript函数
Apr 07 #Javascript
vue实现拖拽交换位置
Apr 07 #Vue.js
使用Ajax实现进度条的绘制
Vue.Draggable实现交换位置
vue-cli3.0修改打包后的文件名和文件地址,打包后本地运行报错解决
You might like
CodeIgniter上传图片成功的全部过程分享
2013/08/12 PHP
zend framework文件上传功能实例代码
2013/12/25 PHP
thinkPHP学习笔记之安装配置篇
2015/03/05 PHP
浅谈PHP中静态方法和非静态方法的相互调用
2016/10/04 PHP
ThinkPHP5.0框架结合Swoole开发实现WebSocket在线聊天案例详解
2019/04/02 PHP
ThinkPHP5.1框架页面跳转及修改跳转页面模版示例
2019/05/06 PHP
javascript add event remove event
2008/04/07 Javascript
由document.body和document.documentElement想到的
2009/04/13 Javascript
jsTree树控件(基于jQuery, 超强悍)[推荐]
2009/09/01 Javascript
js下将字符串当函数执行的方法
2011/07/13 Javascript
加载远程图片时,经常因为缓存而得不到更新的解决方法(分享)
2013/06/26 Javascript
ExtJS4给Combobox设置列表中的默认值示例
2014/05/02 Javascript
Bootstrap Table使用方法详解
2016/08/01 Javascript
卸载安装Node.js与npm过程详解
2016/08/15 Javascript
vue双向绑定简要分析
2017/03/23 Javascript
js模块加载方式浅析
2017/08/12 Javascript
详解微信小程序canvas圆角矩形的绘制的方法
2018/08/22 Javascript
VUE2.0+ElementUI2.0表格el-table循环动态列渲染的写法详解
2018/11/30 Javascript
JavaScript this绑定过程深入详解
2018/12/07 Javascript
electron实现静默打印的示例代码
2019/08/12 Javascript
vue.js中ref及$refs的使用方法解析
2019/10/08 Javascript
Vue 解决通过this.$refs来获取DOM或者组件报错问题
2020/07/28 Javascript
[56:13]DOTA2-DPC中国联赛定级赛 LBZS vs Phoenix BO3第一场 1月10日
2021/03/11 DOTA
用Python程序抓取网页的HTML信息的一个小实例
2015/05/02 Python
pandas数值计算与排序方法
2018/04/12 Python
python实现简单flappy bird
2018/12/24 Python
Pythony运维入门之Socket网络编程详解
2019/04/15 Python
连接pandas以及数组转pandas的方法
2019/06/28 Python
JupyterNotebook设置Python环境的方法步骤
2019/12/03 Python
公司培训欢迎词
2014/01/10 职场文书
2014会计年终工作总结
2014/12/20 职场文书
2015年化验室工作总结
2015/04/23 职场文书
班主任开场白
2015/06/01 职场文书
员工考勤管理制度
2015/08/06 职场文书
汶川大地震感悟
2015/08/10 职场文书
5种 JavaScript 方式实现数组扁平化
2021/10/05 Javascript