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 动态添加样式规则 W3C校检
Dec 25 Javascript
为JavaScript提供睡眠功能(sleep) 自编译JS引擎
Aug 16 Javascript
Extjs4中Form的使用之本地hiddenfield
Nov 26 Javascript
浅谈JS中的bind方法与函数柯里化
Aug 10 Javascript
MUI 解决动态列表页图片懒加载再次加载不成功的bug问题
Apr 13 Javascript
详解JavaScript数组过滤相同元素的5种方法
May 23 Javascript
使用json-server简单完成CRUD模拟后台数据的方法
Jul 12 Javascript
vue打包之后生成一个配置文件修改接口的方法
Dec 09 Javascript
说说Vuex的getters属性的具体用法
Apr 15 Javascript
js实现复制粘贴的两种方法
Dec 04 Javascript
swiperjs实现导航与tab页的联动
Dec 13 Javascript
Vue Element UI自定义描述列表组件
May 18 Vue.js
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.3新特性命名空间规则解析及高级功能
2010/03/11 PHP
php笔记之:数据类型与常量的使用分析
2013/05/14 PHP
Yii框架调试心得--在页面输出执行sql语句
2014/12/25 PHP
phpQuery让php处理html代码像jQuery一样方便
2015/01/06 PHP
phplist及phpmailer(组合使用)通过gmail发送邮件的配置方法
2016/03/30 PHP
PHP与Web页面的交互示例详解二
2020/08/04 PHP
Jquery选择器 $实现原理
2009/12/02 Javascript
为超链接加上disabled后的故事
2010/12/10 Javascript
javascript模版引擎-tmpl的bug修复与性能优化分析
2011/10/23 Javascript
jQuery之选项卡的简单实现
2014/02/28 Javascript
jQuery.Form实现Ajax上传文件同时设置headers的方法
2017/06/26 jQuery
使用Vue写一个datepicker的示例
2018/01/27 Javascript
Bootstrap table表格初始化表格数据的方法
2018/07/25 Javascript
微信小程序自定义导航栏
2018/12/31 Javascript
微信小程序封装自定义弹窗的实现代码
2019/05/08 Javascript
使用jQuery mobile NuGet让你的网站在移动设备上同样精彩
2019/06/18 jQuery
python实现清屏的方法
2015/04/30 Python
Python的Flask框架应用调用Redis队列数据的方法
2016/06/06 Python
更改Ubuntu默认python版本的两种方法python-> Anaconda
2016/12/18 Python
Python搭建HTTP服务器和FTP服务器
2017/03/09 Python
python3读取csv和xlsx文件的实例
2018/06/22 Python
Python爬虫实现抓取京东店铺信息及下载图片功能示例
2018/08/07 Python
Tensorflow分类器项目自定义数据读入的实现
2019/02/05 Python
Python 过滤错误log并导出的实例
2019/12/26 Python
python判断两个序列的成员是否一样的实例代码
2020/03/01 Python
Python小白学习爬虫常用请求报头
2020/06/03 Python
使用PyCharm安装pytest及requests的问题
2020/07/31 Python
python Autopep8实现按PEP8风格自动排版Python代码
2021/03/02 Python
HTML5 canvas画图并保存成图片的jcanvas插件
2014/01/17 HTML / CSS
浅谈react路由传参的几种方式
2021/03/23 Javascript
laravel使用redis队列实例讲解
2021/03/23 PHP
银行职员自我鉴定
2014/04/20 职场文书
2014年后勤工作总结范文
2014/12/16 职场文书
二手房购房意向书
2015/05/09 职场文书
简爱读书笔记
2015/06/26 职场文书
如果用一句诗总结你的上半年,你会用哪句呢?
2019/07/16 职场文书