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 相关文章推荐
加速IE的Javascript document输出的方法
Dec 02 Javascript
jQuery DOM操作实例
Mar 05 Javascript
详解AngularJS中的filter过滤器用法
Jan 04 Javascript
在Web项目中引入Jquery插件报错的完美解决方案(图解)
Sep 19 Javascript
JS键盘版计算器的制作方法
Dec 03 Javascript
详解Jquery 遍历数组之$().each方法与$.each()方法介绍
Jan 09 Javascript
jQuery快速实现商品数量加减的方法
Feb 06 Javascript
js获取元素的偏移量offset简单方法(必看)
Jul 05 Javascript
ES6学习教程之对象字面量详解
Oct 09 Javascript
详解VUE里子组件如何获取父组件动态变化的值
Dec 26 Javascript
实例分析编写vue组件方法
Feb 12 Javascript
react实现复选框全选和反选组件效果
Aug 25 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
PHP 5.0 Pear安装方法
2006/12/06 PHP
discuz安全提问算法
2007/06/06 PHP
php获取从html表单传递数组的方法
2015/03/20 PHP
windows 2008r2+php5.6.28环境搭建详细过程
2019/06/18 PHP
实例化php类时传参的方法分析
2020/06/05 PHP
用Javascript 和 CSS 实现脚注(Footnote)效果
2009/09/09 Javascript
原生JS操作网页给p元素添加onclick事件及表格隔行变色
2013/12/01 Javascript
js取float型小数点后两位数的方法
2014/01/18 Javascript
Javascript中this的用法详解
2014/09/22 Javascript
JS动态显示表格上下frame的方法
2015/03/31 Javascript
JavaScript使用ActiveXObject访问Access和SQL Server数据库
2015/04/02 Javascript
深入浅析JavaScript的API设计原则
2016/06/14 Javascript
javascript基本数据类型及类型检测常用方法小结
2016/12/14 Javascript
Angular之指令Directive用法详解
2017/03/01 Javascript
node.js程序作为服务并在windows下开机自启动(用forever)
2017/03/29 Javascript
在vue.js中抽出公共代码的方法示例
2017/06/08 Javascript
Three.js实现浏览器变动时进行自适应的方法
2017/09/26 Javascript
vue项目实战总结篇
2018/02/11 Javascript
vue中使用codemirror的实例详解
2018/11/01 Javascript
jquery层次选择器的介绍
2019/01/18 jQuery
ES6知识点整理之数组解构和字符串解构的应用示例
2019/04/17 Javascript
JavaScript鼠标拖拽事件详解
2020/04/03 Javascript
[01:16]DOTA2小知识课堂 Ep.03 芒果树无伤肉山
2019/12/05 DOTA
python字典多条件排序方法实例
2014/06/30 Python
python查看zip包中文件及大小的方法
2015/07/09 Python
对python使用http、https代理的实例讲解
2018/05/07 Python
python ---lambda匿名函数介绍
2019/03/13 Python
美国背景检查、公共记录和人物搜索网站:BeenVerified
2018/02/25 全球购物
Otticanet意大利:最顶尖的世界名牌眼镜, 能得到打折季的价格
2019/03/10 全球购物
Servlet都有哪些方法?主要作用是什么?
2014/03/04 面试题
挂职自我鉴定
2014/02/26 职场文书
演讲稿开场白台词
2014/08/25 职场文书
工作证明范本(2篇)
2014/09/14 职场文书
比赛主持人开场白
2015/05/29 职场文书
Python爬取某拍短视频
2021/06/11 Python
python数字类型和占位符详情
2022/03/13 Python