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 相关文章推荐
JQuery中getJSON的使用方法
Dec 13 Javascript
JS随机生成不重复数据的实例方法
Jul 17 Javascript
自己写的Javascript计算时间差函数
Oct 28 Javascript
jQuery老黄历完整实现方法
Jan 16 Javascript
JavaScript将数字转换成大写中文的方法
Mar 23 Javascript
基于JavaScript实现生成名片、链接等二维码
Sep 20 Javascript
详解JavaScript时间处理之几个月前或几个月后的指定日期
Dec 21 Javascript
原生JS实现幻灯片
Feb 22 Javascript
js如何编写简单的ajax方法库
Aug 02 Javascript
彻底弄懂 JavaScript 执行机制
Oct 23 Javascript
bootstrap 日期控件 datepicker被弹出框dialog覆盖的解决办法
Jul 09 Javascript
vue如何使用模拟的json数据查看效果
Mar 31 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的配置文件php.ini
2006/10/09 PHP
php 购物车的例子
2009/05/04 PHP
PHP编程文件处理类SplFileObject和SplFileInfo用法实例分析
2017/07/22 PHP
laravel + vue实现的数据统计绘图(今天、7天、30天数据)
2018/07/31 PHP
Yii框架响应组件用法实例分析
2019/09/04 PHP
超级简单的图片防盗(HTML),好用
2007/04/08 Javascript
jQuery 注意事项 与原因分析
2009/04/24 Javascript
Javascript 两个窗体之间传值实现代码
2009/09/25 Javascript
js的写法基础分析
2011/01/17 Javascript
jQuery 全选/反选以及单击行改变背景色实例
2013/07/02 Javascript
javascript获取checkbox复选框获取选中的选项
2014/08/12 Javascript
基于jQuery实现在线选座之高铁版
2015/08/24 Javascript
JavaScript观察者模式(经典)
2015/12/09 Javascript
jQuery animate easing使用方法图文详解
2016/06/17 Javascript
浅谈jQuery this和$(this)的区别及获取$(this)子元素对象的方法
2016/11/29 Javascript
超全面的JavaScript开发规范(推荐)
2017/01/21 Javascript
js实现日历与定时器
2017/02/22 Javascript
JavaScript实现两个select下拉框选项左移右移
2017/03/09 Javascript
浅谈VUE-CLI脚手架热更新太慢的原因和解决方法
2018/09/28 Javascript
Node.js之删除文件夹(含递归删除)代码实例
2019/09/09 Javascript
Python中unittest模块做UT(单元测试)使用实例
2015/06/12 Python
python学习笔记之调用eval函数出现invalid syntax错误问题
2015/10/18 Python
Python 专题六 局部变量、全局变量global、导入模块变量
2017/03/20 Python
Python使用装饰器进行django开发实例代码
2018/02/06 Python
解决Python 使用h5py加载文件,看不到keys()的问题
2019/02/08 Python
Python骚操作之动态定义函数
2019/03/26 Python
html5 css3 动态气泡按钮实例演示
2012/12/02 HTML / CSS
css3实现顶部社会化分享按钮示例
2014/05/06 HTML / CSS
HTML5之SVG 2D入门4—笔画与填充
2013/01/30 HTML / CSS
iframe跨域的几种常用方法
2019/11/11 HTML / CSS
mysql的最长数据库名,表名,字段名可以是多长
2014/04/21 面试题
电气工程及其自动化自我评价四篇
2013/09/24 职场文书
大学生蛋糕店创业计划书
2014/01/13 职场文书
新学期班主任寄语
2014/01/18 职场文书
工程质量承诺书范文
2014/03/27 职场文书
共青团员自我评价范文
2014/09/14 职场文书