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 定义function的三种方式小结
Oct 16 Javascript
javascript 防止刷新,后退,关闭
Aug 07 Javascript
jQuery向后台传入json格式数据的方法
Feb 13 Javascript
Angular JS数据的双向绑定详解及实例
Dec 31 Javascript
js select下拉联动 更具级联性!
Apr 17 Javascript
微信小程序 Template详解及简单实例
Jan 05 Javascript
jQuery实现贪吃蛇小游戏(附源码下载)
Mar 04 Javascript
深入了解javascript 数组的sort方法
Jun 01 Javascript
小程序rich-text组件如何改变内部img图片样式的方法
May 22 Javascript
对layer弹出框中icon数字参数的说明介绍
Sep 04 Javascript
JQuery 实现文件下载的常用方法分析
Oct 29 jQuery
微信小程序实现图片压缩
Dec 03 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
非洲第一个咖啡超凡杯大赛承办国—卢旺达的咖啡怎么样
2021/03/03 咖啡文化
PHP中foreach()用法汇总
2015/07/02 PHP
PHP中ajax无刷新上传图片与图片下载功能
2017/02/21 PHP
PHP获取真实客户端的真实IP
2017/03/07 PHP
PHP中关于php.ini参数优化详解
2020/02/28 PHP
phpstudy2020搭建站点的实现示例
2020/10/30 PHP
javascript中利用数组实现的循环队列代码
2010/01/24 Javascript
jQuery移除元素自动解绑事件实现思路及代码
2014/05/31 Javascript
javascript实现的多个层切换效果通用函数实例
2015/07/06 Javascript
轻松实现Bootstrap图片轮播
2020/04/20 Javascript
Ajax使用原生态JS验证用户名是否存在
2020/05/26 Javascript
jQuery选择器实例应用
2017/01/05 Javascript
JS中的数组转变成JSON格式字符串的方法
2017/05/09 Javascript
微信小程序报错:this.setData is not a function的解决办法
2017/09/27 Javascript
vue-better-scroll 的使用实例代码详解
2018/12/03 Javascript
ES6 Proxy实现Vue的变化检测问题
2019/06/11 Javascript
node获取客户端ip功能简单示例
2019/08/24 Javascript
微信小程序添加插屏广告并设置显示频率(一天一次)
2019/12/06 Javascript
React实现todolist功能
2020/12/28 Javascript
[02:09]DOTA2辉夜杯 EHOME夺冠举杯现场
2015/12/28 DOTA
[02:53]2018年度DOTA2最佳战队-完美盛典
2018/12/17 DOTA
常用python编程模板汇总
2016/02/12 Python
Python爬虫 scrapy框架爬取某招聘网存入mongodb解析
2019/07/31 Python
Pycharm最新激活码2019(推荐)
2019/12/31 Python
浅谈html5增强的页面元素
2016/06/14 HTML / CSS
阿联酋团购网站:Groupon阿联酋
2016/10/14 全球购物
利用指针变量实现队列的入队操作
2012/04/07 面试题
高三自我鉴定范文
2013/10/19 职场文书
竞选班长的演讲稿
2014/04/24 职场文书
岗位明星事迹材料
2014/05/18 职场文书
六查六看六改心得体会
2014/10/14 职场文书
2015年反腐倡廉工作总结
2015/05/14 职场文书
Django项目如何获得SSL证书与配置HTTPS
2021/04/30 Python
你真的了解redis为什么要提供pipeline功能
2021/06/22 Redis
JavaScript 事件捕获冒泡与捕获详情
2021/11/11 Javascript
linux目录管理方法介绍
2022/06/01 Servers