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 相关文章推荐
用js来解决ajax读取页面乱码
Nov 28 Javascript
jquery触发a标签跳转事件示例代码
Jul 21 Javascript
文本有关的样式和jQuery求对象的高宽问题分别说明
Aug 30 Javascript
浅析JavaScript回调函数应用
May 22 Javascript
很棒的Bootstrap选项卡切换效果
Jul 01 Javascript
深入理解JavaScript中的块级作用域、私有变量与模块模式
Oct 31 Javascript
浅谈在react中如何实现扫码枪输入
Jul 04 Javascript
JavaScript插入排序算法原理与实现方法示例
Aug 06 Javascript
vue-router权限控制(简单方式)
Oct 29 Javascript
Vue.js样式动态绑定实现小结
Jan 24 Javascript
Vue开发之封装分页组件与使用示例
Apr 25 Javascript
vue element 关闭当前tab 跳转到上一路由操作
Jul 22 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世纪万年历
2006/12/06 PHP
php实现简单的守护进程创建、开启与关闭操作
2019/08/13 PHP
PHP CURL实现模拟登陆并上传文件操作示例
2020/01/02 PHP
javascript实现划词标记+划词搜索功能
2007/03/06 Javascript
javascript面向对象包装类Class封装类库剖析
2013/01/24 Javascript
使用CSS样式position:fixed水平滚动的方法
2014/02/19 Javascript
js取模(求余数)隔行变色
2014/05/15 Javascript
js Canvas实现圆形时钟教程
2016/09/19 Javascript
ionic3 懒加载
2017/08/16 Javascript
JavaScript如何获取到导航条中HTTP信息
2017/10/10 Javascript
使用VueCli3+TypeScript+Vuex一步步构建todoList的方法
2019/07/25 Javascript
解决Layui当中的导航条动态添加后渲染失败的问题
2019/09/25 Javascript
js实现九宫格抽奖
2020/03/19 Javascript
使用vue3重构拼图游戏的实现示例
2021/01/25 Vue.js
[01:14]英雄,所敬略同——2018完美盛典宣传视频
2018/12/05 DOTA
python生成指定长度的随机数密码
2014/01/23 Python
python利用Opencv实现人脸识别功能
2019/04/25 Python
详解Django模版中加载静态文件配置方法
2019/07/21 Python
python虚拟环境完美部署教程
2019/08/06 Python
Pytorch反向求导更新网络参数的方法
2019/08/17 Python
Anaconda之conda常用命令介绍(安装、更新、删除)
2019/10/06 Python
关于python pycharm中输出的内容不全的解决办法
2020/01/10 Python
python实现npy格式文件转换为txt文件操作
2020/07/01 Python
如何在mac版pycharm选择python版本
2020/07/21 Python
爱尔兰电脑、家电和家具购物网站:Buy It Direct
2019/07/09 全球购物
西部世纪.net笔试题面试题
2014/04/03 面试题
几个判断型的面试题
2012/07/03 面试题
教师现实表现材料
2014/02/14 职场文书
社区健康教育实施方案
2014/03/18 职场文书
工商企业管理专业自荐信范文
2014/04/12 职场文书
市委常委班子党的群众路线教育实践活动整改措施
2014/10/02 职场文书
人民的好儿女观后感
2015/06/18 职场文书
2015-2016年小学教导工作总结
2015/07/21 职场文书
《金钱的魔力》教学反思
2016/02/20 职场文书
驾驶员安全责任协议书
2016/03/22 职场文书
Python类方法总结讲解
2021/07/26 Python