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之三(封装和信息隐藏)
Jan 27 Javascript
js实现在页面上弹出蒙板技巧简单实用
Apr 16 Javascript
JavaScript作用域链使用介绍
Aug 29 Javascript
浅谈JavaScript异常处理语句
Jun 26 Javascript
jquery中实现时间戳与日期相互转换
Apr 12 Javascript
node.js实现端口转发
Apr 14 Javascript
微信小程序 登录的简单实现
Apr 19 Javascript
Vue中定义全局变量与常量的各种方式详解
Aug 23 Javascript
VUE长按事件需求详解
Oct 18 Javascript
AngularJs点击状态值改变背景色的实例
Dec 18 Javascript
JS实现碰撞检测的方法分析
Jan 19 Javascript
bootstrapTable+ajax加载数据 refresh更新数据
Aug 31 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中利用str_pad函数生成数字递增形式的产品编号
2013/09/30 PHP
使用Discuz关键词服务器实现PHP中文分词
2014/03/11 PHP
php类的自动加载操作实例详解
2016/09/28 PHP
JavaScript Accessor实现说明
2010/12/06 Javascript
jquery设置text的值示例(设置文本框 DIV 表单值)
2014/01/06 Javascript
Javascript 遍历页面text控件详解
2014/01/06 Javascript
JavaScript对象学习小结
2015/09/02 Javascript
原生js实现百叶窗效果及原理介绍
2016/04/12 Javascript
Bootstrap下拉菜单Dropdowns的实现代码
2017/03/17 Javascript
详解vue项目构建与实战
2017/06/27 Javascript
利用types增强vscode中js代码提示功能详解
2017/07/07 Javascript
BetterScroll 在移动端滚动场景的应用
2017/09/18 Javascript
在vue中添加Echarts图表的基本使用教程
2017/11/22 Javascript
使用post方法实现json往返传输数据的方法
2019/03/30 Javascript
了解JavaScript表单操作和表单域
2019/05/27 Javascript
微信小程序使用canvas自适应屏幕画海报并保存图片功能
2019/07/25 Javascript
Electron 打包问题:electron-builder 下载各种依赖出错(推荐)
2020/07/09 Javascript
[45:18]2018DOTA2亚洲邀请赛 4.3 突围赛 Optic vs iG 第一场
2018/04/04 DOTA
Python单元测试框架unittest使用方法讲解
2015/04/13 Python
在Python的Django框架中获取单个对象数据的简单方法
2015/07/17 Python
Python抓取电影天堂电影信息的代码
2016/04/07 Python
Windows中安装使用Virtualenv来创建独立Python环境
2016/05/31 Python
老生常谈Python之装饰器、迭代器和生成器
2017/07/26 Python
Python中的浮点数原理与运算分析
2017/10/12 Python
python机器学习实战之树回归详解
2017/12/20 Python
用Python写一段用户登录的程序代码
2018/04/22 Python
Window 64位下python3.6.2环境搭建图文教程
2018/09/19 Python
Python数据可视化库seaborn的使用总结
2019/01/15 Python
flask应用部署到服务器的方法
2019/07/12 Python
快速解决jupyter notebook启动需要密码的问题
2020/04/21 Python
HTML5教程之html 5 本地数据库(Web Sql Database)
2014/04/03 HTML / CSS
CK美国官网:Calvin Klein
2016/08/26 全球购物
食品安全工作实施方案
2014/03/26 职场文书
运动员获奖感言
2014/08/15 职场文书
重阳节座谈会主持词
2015/07/03 职场文书
Python使用pandas导入csv文件内容的示例代码
2022/12/24 Python